-
Notifications
You must be signed in to change notification settings - Fork 27
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
chore(decrypt): specify behavior on decrypt with encryption context #261
base: master
Are you sure you want to change the base?
Conversation
It MUST be required that the decryption materials obtained from the underlying CMM's MUST | ||
contain all configured encryption context keys in its encryption context and the values MUST remain | ||
unchanged. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure what this means. What is a "configured encryption conext key? How do we enforce they remain unchanged?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"configured encryption conext key" this should be "required encryption context key"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am trying to get at is that if the CMM returns encryption context which IS stored AND one of the keys in the required encryption context is also in this encryption context then the value in their key-value pair mapping MUST remain unchanged
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we break down what's in the PR:
contain all required encryption context key in (the decryption material's) encryption context
This is already a requirement on decryption materials. If a "key" is required, that key-value pair must exist in the encryption context on those materials.
the values (of the required encryption context keys? or all EC values?) MUST remain unchanged (from what?)
Which values? (it should be the values corresponding to the required encryption context keys)
What does "unchanged" mean? Unchanged from what? (Unchanged from the EC in the header, if that key also exists in the header)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It MUST be required that the decryption materials obtained from the underlying CMM's MUST | |
contain all configured encryption context keys in its encryption context and the values MUST remain | |
unchanged. | |
The decryption materials obtained from the underlying CMM's MUST | |
contain all required encryption context keys in its encryption context and the values MUST remain | |
unchanged. |
Is the problem that https://github.com/awslabs/aws-encryption-sdk-specification/blob/master/framework/cmm-interface.md#decrypt-materials
The CMM MUST validate the Encryption Context by comparing it to the customer supplied Reproduced Encryption Context in decrypt materials request. For every key that exists in both Reproduced Encryption Context and Encryption Context, the values MUST be equal or the operation MUST fail.
is not a post condition?
### Test Different Encryption Context on Decrypt Failure | ||
|
||
Encrypt with and store all encryption context in the message header. | ||
On Decrypt will supply additional encryption context not stored in the header. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is testing a total disjoint between expected EC and inputted EC. We should seperately test "inputted EC is missing a pair", "inputted EC has an incorrect value for one pair", and "inputted EC has an extra pair".
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking at the tests below, I think we cover all of these except "inputted EC has an extra pair"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
adding in latest revision
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As set up, this could fail due to either:
- reproduced EC missing required key-value pairs
- reproduced EC including an extra key-value pair
Which one do we want this test to target?
// Test supply same encryption context on encrypt and decrypt NO filtering | ||
var encryptionContext := map[ keyA := valA, keyB := valB ]; | ||
var reproducedAdditionalEncryptionContext := map[ keyA := valB, keyB := valA ]; | ||
var requiredEncryptionContextKeys := [keyA, keyB]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I thought this was testing context that is in the header?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yup good catch
NOT some key-value pair that the underlying CMM MAY have modified. | ||
|
||
If required keys exist, match stored encryption context, AND decryption succeeds | ||
Decrypt MUST return both the Encryption Context stored in the header AND the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This "AND" is ambiguous. I believe it should be the union of these maps.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually, should it just replicate our logic for inclusion in the header validation?
i.e. Every key-value pair in the header, and every "required" key-value pair in the EC?
Co-authored-by: lavaleri <49660121+lavaleri@users.noreply.github.com>
Decrypt returns Encryption Context. | ||
This requirement may be satisfied by returning the parsed header that contains this value. | ||
|
||
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. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: I'd flip the order of these and edit it to say that we used to be able to satisfy the requirement by just returning the header, but that is no longer the case, as the header may not contain all EC values used to authenticate the message anymore.
It MUST be required that the decryption materials obtained from the underlying CMM's MUST | ||
contain all configured encryption context keys in its encryption context and the values MUST remain | ||
unchanged. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we break down what's in the PR:
contain all required encryption context key in (the decryption material's) encryption context
This is already a requirement on decryption materials. If a "key" is required, that key-value pair must exist in the encryption context on those materials.
the values (of the required encryption context keys? or all EC values?) MUST remain unchanged (from what?)
Which values? (it should be the values corresponding to the required encryption context keys)
What does "unchanged" mean? Unchanged from what? (Unchanged from the EC in the header, if that key also exists in the header)
|
||
On Encrypt will write all encryption context supplied to the message. | ||
On Decrypt will have a Required Encryption Context CMM that requires all encryption context | ||
on Decrypt. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This MUST succeed.
### Test Different Encryption Context on Decrypt Failure | ||
|
||
Encrypt with and store all encryption context in the message header. | ||
On Decrypt will supply additional encryption context not stored in the header. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As set up, this could fail due to either:
- reproduced EC missing required key-value pairs
- reproduced EC including an extra key-value pair
Which one do we want this test to target?
|
||
// Test supply same encryption context on encrypt and decrypt NO filtering | ||
var encryptionContext := map[ keyA := valA, keyB := valB ]; | ||
var reproducedAdditionalEncryptionContext := map[ keyA := valA, keyB := valB, keyC := valC ]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To test mismatch, don't you want this to be something like map[ keyA := valA, keyB := valC ];
? i.e. the keys are correct but the values are not? Otherwise this is testing "extra unexpected key-value pair" again.
|
||
Encrypt will NOT store all encryption context. | ||
Decrypt will NOT supply reproduced encryption context. | ||
This operation MUST fail. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this failing due to the Required Encryption Context CMM, or is authentication failing? Which are we trying to put under test? These descriptions should make clear whether or not the REC CMM is involved or not.
:: decryptionMaterials[k] == headerEncryptionContext[k] | ||
``` | ||
|
||
## Testing |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thinking more about this, I think it would be better to more clearly define what the matrix is we care about, as opposed to listing out the different tests and code for them. I would prefer we cut the example code, but make it extremely clear what every case we need to check is in a way that makes it easy to reason that it is complete. For example, maybe frame it like this:
First, suppose we have a message where {A:B,C:D} is in the header, and {E:F} is not stored, but is included in the authentication.
For this message, go through the following test cases:
- customer supplies correct required key-value {E:F} (SUCCESS)
- customer supplies correct required key-value and additional correct header value {A:B,E:F} (SUCCESS)
- customer supplies does not supply required key-value {} (FAILURE)
- customer supplies incorrect value for required key-value {E:X} (FAILURE)
- customer supplies correct required key-value and additional incorrect header value {A:X,E:F} (FAILURE)
- customer supplies correct required key-value and additional incorrect, non-header key-value {E:F,X:Y} (FAILURE)
For every one of the above cases, attempt to decrypt using both a Default CMM, and a REC CMM with E configured as a "required key".
Next, suppose we have a message where {A:B,C:D,E:F} is in the header, and there is no additional non-stored key-values authenticated with the message.
For this message, go through the following test cases:
- customer supplies no reproduced context {} (SUCCESS)
- customer supplies additional correct header values {A:B,C:D,E:F} (SUCCESS)
- customer supplies incorrect value for key in header {A:X} (FAILURE)
- customer supplies incorrect, non-header key-value {X:Y} (FAILURE)
For each of these use a Default CMM.
This is more test cases than we currently have, and we may be able to convince ourselves that some of those test cases are not actually useful. However, I would prefer if this document focused on listing the parameters for the test cases in a way that is easy for readers to see whether we are missing any (And if we decide any are not useful, say why). If we do this, I don't think we need to give example code for each test case.
client-apis/decrypt.md
Outdated
@@ -162,6 +164,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, if available. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
encryption context for authentication only
Can we point to the definition of this somewhere?
It MUST be required that the decryption materials obtained from the underlying CMM's MUST | ||
contain all configured encryption context keys in its encryption context and the values MUST remain | ||
unchanged. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It MUST be required that the decryption materials obtained from the underlying CMM's MUST | |
contain all configured encryption context keys in its encryption context and the values MUST remain | |
unchanged. | |
The decryption materials obtained from the underlying CMM's MUST | |
contain all required encryption context keys in its encryption context and the values MUST remain | |
unchanged. |
Is the problem that https://github.com/awslabs/aws-encryption-sdk-specification/blob/master/framework/cmm-interface.md#decrypt-materials
The CMM MUST validate the Encryption Context by comparing it to the customer supplied Reproduced Encryption Context in decrypt materials request. For every key that exists in both Reproduced Encryption Context and Encryption Context, the values MUST be equal or the operation MUST fail.
is not a post condition?
The Decrypt API MUST return the set of the union of the encryption context stored in the header and the encryption | ||
context used for authentication only. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree but this feels like a jump.
The Decrypt API MUST return the set of the union of the encryption context stored in the header and the encryption | ||
context used for authentication only. | ||
|
||
### What changes to the existing Required Encryption Context CMM are required? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are there any changes to the CMM interface?
Decrypt MUST verify that if the keys in the required encryption context keys exist in the reproduced encryption context | ||
AND they are stored in the message header, they MUST have the same value as the reproduced encryption context supplied. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is not how you have change the spec:
- If a [required encryption context key](../framework/structures.md#required-encryption-context-keys) in
the decryption materials' response exists in the [message header body](../data-format/message-header.md#header-body)
the value in the decryption materials' encryption context MUST equal the value stored in the message header body.
If you want what you have specified, then I think you need:
Decrypt MUST verify that if the keys in the required encryption context keys exist in the reproduced encryption context | |
AND they are stored in the message header, they MUST have the same value as the reproduced encryption context supplied. | |
For required encryption context keys the value in stored in the message header | |
MUST equal the value in decryption materials encryption context. |
da25ba4
to
656459a
Compare
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 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The `decrypt` API SHOULD not check if the encryption context that was stored on the message matches | |
The `decrypt` API SHOULD NOT check if the encryption context that was stored on the message matches |
|
||
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 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Stronger than built-in.
It constructs the 2 sets of EC from a single set.
So these 2 sets (stored/not stored) MUST be disjoint.
- `{ b: b, c: c}` | ||
- `{ a: a, b: b, c: c }` | ||
|
||
### Message: `{a: a, b: b}` / `{}` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we can further wordsmith these tables to simplify.
But this is a good start!
- 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 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As described by the CMM in the decryption materials? Otherwise this is "the same" as "Not stored EC"
- `{a: a, b: b}` / `{a}` | ||
- `{a: a, b: b}` / `{a,b}` | ||
- `{a: a, b: c}` / `{a}` | ||
- `{a: a, b: b}` / `{c}` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The specification for decryption materials doesn't allow this case.
| CMM Material/Required Keys → <br/>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 | |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should expect every column except for the first to always fail during the header authentication step, regardless of the inputted reproduced encryption context. ('a' or 'b' would be incorrectly appended to the header authentication).
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. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We know that by the time you are returning a result that these maps are disjoint, but this won't be something we will be able to prove in dafny... I'm unsure whether we want to specifically make a note in the spec of this expectation or not.
|
||
### Message: `{a: a}` / `{b: b}` | ||
|
||
| CMM Material/Required Keys → <br/>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}` | |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you actually want the message to be {b: b}
/{a: a}
Otherwise, all of these columns should always fail, as the header auth won't ever correctly append a 'b' value during verification, regardless of the reproduced encryption context.
|
||
| CMM Material/Required Keys → <br/>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 | |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We may want to represent some of these as N/As. For example, if the reproduced context does not contain b
, how would the CMM ever be able to return a 'b'.
It may be easier to reason about this matrix if we represent the obviously wrong values with something like x
, to better indicate that this is just some junk value, and is possible for the CMM to add to the EC.
|
||
### Message:`{}` / `{a: a, b: b}` | ||
|
||
| CMM Material/Required Keys → <br/>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}` | |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Similar to the other tables, I think that {a: a, b: b} / {} is the only column that could ever succeed.
- `{a: a}` / `{b: b}` | ||
- `{}` / `{a: a, b: b}` | ||
|
||
CMM Material/Required Keys |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is missing:
{a: a, b: b, x: x}
/{a}
{a: x, b: b}
/{a}
Issue #, if available:
Description of changes:
By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.
Check any applicable: