Skip to content
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

feat(DynamoDbEncryption): Add GetEncryptedDataKeyDescription operation #856

Merged
merged 74 commits into from
May 10, 2024
Merged
Show file tree
Hide file tree
Changes from 60 commits
Commits
Show all changes
74 commits
Select commit Hold shift + click to select a range
0f80010
Add parser
rishav-karanjit Mar 19, 2024
a5944c6
Fixed verify
rishav-karanjit Mar 22, 2024
689e83d
Updated Smithy to make keyProviderInfo optional
rishav-karanjit Mar 25, 2024
8f720cd
Added preconditions for GetEncryptedDataKeyDescription operation
rishav-karanjit Mar 25, 2024
79b70da
Add unit test for DynamoDbGetEncryptedDataKeyDescription
rishav-karanjit Mar 25, 2024
24f8f90
Added specification for Get Encrypted Data Key Description
rishav-karanjit Mar 25, 2024
346bf27
Refactor GetEncryptedDataKeyDescription operation
rishav-karanjit Mar 25, 2024
e909d69
Refactor the tests
rishav-karanjit Mar 25, 2024
7de56f3
Add more info in comments
rishav-karanjit Mar 25, 2024
d72193e
Add smithy generated java files
rishav-karanjit Mar 25, 2024
44f22b7
Removed exception for custom keyring
rishav-karanjit Mar 26, 2024
447630d
Add polymorph generated code
rishav-karanjit Mar 26, 2024
5d0a9fb
Revert "Add polymorph generated code"
rishav-karanjit Mar 26, 2024
09b6134
Add GetEncryptedDataKeyDescription Example
rishav-karanjit Mar 26, 2024
9deae04
Add more test coverage and decrease resource count
rishav-karanjit Mar 26, 2024
23b5de7
Add getBranchKeyVersion to decrease resource count
rishav-karanjit Mar 27, 2024
6bc3da1
Merge branch 'main' into rishav-feat-parser
rishav-karanjit Mar 27, 2024
ee7ba8d
Add polymorph generated code
rishav-karanjit Mar 27, 2024
dda196a
Add some more generated dotnet
rishav-karanjit Mar 27, 2024
6e6fd6b
format code
rishav-karanjit Mar 27, 2024
9fc726f
Add copyright and license in the comments
rishav-karanjit Mar 27, 2024
0ebcbe3
Add dotnet example
rishav-karanjit Mar 28, 2024
f1a0051
format code
rishav-karanjit Mar 28, 2024
8e8d19e
Merge branch 'main' of https://github.com/aws/aws-database-encryption…
rishav-karanjit Mar 28, 2024
707ecf7
Merge format
rishav-karanjit Mar 28, 2024
8c7bcaf
fix: merge errors
rishav-karanjit Mar 28, 2024
85ea703
Fix examples
rishav-karanjit Mar 28, 2024
6b4a324
removed unused variable
rishav-karanjit Mar 28, 2024
1810c1d
Fix example
rishav-karanjit Mar 28, 2024
900c398
Format dafny code
rishav-karanjit Mar 28, 2024
9275151
Add comments to dotnet example
rishav-karanjit Mar 29, 2024
fe44b3f
Update dafny test
rishav-karanjit Mar 29, 2024
29ab4f5
Add dotnet generated
rishav-karanjit Mar 29, 2024
0811022
Add smithy generated java
rishav-karanjit Mar 29, 2024
39668ed
Add dotnet typeconversion
rishav-karanjit Mar 29, 2024
5e6294a
Revert head to 3 commits back
rishav-karanjit Apr 1, 2024
0c638cb
Add --local-service-test option and did polymorph
rishav-karanjit Apr 1, 2024
98849ee
Refactor to remove extra blank line to make the code look better
rishav-karanjit Apr 2, 2024
7c17ef5
Format dafny code
rishav-karanjit Apr 2, 2024
75ac9a4
Refactor code and add comments
rishav-karanjit Apr 2, 2024
d73839a
Add comments to example
rishav-karanjit Apr 2, 2024
f3e2e71
Update version date
rishav-karanjit Apr 2, 2024
e95ab46
Removed expect
rishav-karanjit Apr 10, 2024
f804374
Removed extract
rishav-karanjit Apr 10, 2024
1d801ef
Assign Salt, IV and Version length constant
rishav-karanjit Apr 10, 2024
4dcb696
format dafny
rishav-karanjit Apr 10, 2024
dc581e7
Remove redundant codes
rishav-karanjit Apr 10, 2024
b28e230
Removed call to ItemToStructured
rishav-karanjit Apr 10, 2024
d9cd376
Remove extract
rishav-karanjit Apr 10, 2024
1cef3ce
Some nits
rishav-karanjit Apr 10, 2024
4c88676
Removed some more extract
rishav-karanjit Apr 10, 2024
5e88171
Updated to appropriate error datatype
rishav-karanjit Apr 10, 2024
6ffde54
Changed structure EncryptedDataKeyDescriptionOutput to EncryptedDataK…
rishav-karanjit Apr 10, 2024
6f6d384
Update specification
rishav-karanjit Apr 10, 2024
d01a432
Add duvet annotation
rishav-karanjit Apr 10, 2024
af31564
put flavor extracting concept inside else block
rishav-karanjit Apr 10, 2024
23d94d1
change < to <=
rishav-karanjit Apr 11, 2024
912305a
fix examples redundancy
rishav-karanjit Apr 11, 2024
88abd76
fix duvet annotations
rishav-karanjit Apr 11, 2024
325b507
Minor nit on specification
rishav-karanjit Apr 11, 2024
d96e977
Add TestNoHeaderFailureCase
rishav-karanjit Apr 18, 2024
756dd0e
Merge branch 'main' into rishav-feat-parser
rishav-karanjit Apr 18, 2024
23804d6
Use another AlgorithmSuites as well
rishav-karanjit Apr 18, 2024
eabe8b2
Merge branch 'main' into rishav-feat-parser
rishav-karanjit Apr 29, 2024
e69af8c
Add polymorph file after merge
rishav-karanjit Apr 30, 2024
5875935
Merge branch 'main' into rishav-feat-parser
rishav-karanjit Apr 30, 2024
9b58508
Add suggested changes
rishav-karanjit May 5, 2024
aa982c3
Merge branch 'main' into rishav-feat-parser
rishav-karanjit May 6, 2024
2f4cfc9
add generated file
rishav-karanjit May 6, 2024
6dedc67
Assert branch key into separate method to reduce resource count
rishav-karanjit May 6, 2024
6b30e4c
Change plainTextItem to item in examples
rishav-karanjit May 6, 2024
16bafa6
Nits in specification
rishav-karanjit May 6, 2024
dff2be6
Fix duvet annotation after nits in specs
rishav-karanjit May 6, 2024
158a98e
Merge branch 'main' into rishav-feat-parser
rishav-karanjit May 10, 2024
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
Original file line number Diff line number Diff line change
Expand Up @@ -91,8 +91,10 @@ module {:extern "software.amazon.cryptography.dbencryptionsdk.dynamodb.internald
class IDynamoDbEncryptionClientCallHistory {
ghost constructor() {
CreateDynamoDbEncryptionBranchKeyIdSupplier := [];
GetEncryptedDataKeyDescription := [];
}
ghost var CreateDynamoDbEncryptionBranchKeyIdSupplier: seq<DafnyCallEvent<CreateDynamoDbEncryptionBranchKeyIdSupplierInput, Result<CreateDynamoDbEncryptionBranchKeyIdSupplierOutput, Error>>>
ghost var GetEncryptedDataKeyDescription: seq<DafnyCallEvent<GetEncryptedDataKeyDescriptionInput, Result<GetEncryptedDataKeyDescriptionOutput, Error>>>
}
trait {:termination false} IDynamoDbEncryptionClient
{
Expand Down Expand Up @@ -145,6 +147,21 @@ module {:extern "software.amazon.cryptography.dbencryptionsdk.dynamodb.internald
ensures CreateDynamoDbEncryptionBranchKeyIdSupplierEnsuresPublicly(input, output)
ensures History.CreateDynamoDbEncryptionBranchKeyIdSupplier == old(History.CreateDynamoDbEncryptionBranchKeyIdSupplier) + [DafnyCallEvent(input, output)]

predicate GetEncryptedDataKeyDescriptionEnsuresPublicly(input: GetEncryptedDataKeyDescriptionInput , output: Result<GetEncryptedDataKeyDescriptionOutput, Error>)
// The public method to be called by library consumers
method GetEncryptedDataKeyDescription ( input: GetEncryptedDataKeyDescriptionInput )
returns (output: Result<GetEncryptedDataKeyDescriptionOutput, Error>)
requires
&& ValidState()
modifies Modifies - {History} ,
History`GetEncryptedDataKeyDescription
// Dafny will skip type parameters when generating a default decreases clause.
decreases Modifies - {History}
ensures
&& ValidState()
ensures GetEncryptedDataKeyDescriptionEnsuresPublicly(input, output)
ensures History.GetEncryptedDataKeyDescription == old(History.GetEncryptedDataKeyDescription) + [DafnyCallEvent(input, output)]

}
datatype DynamoDbEncryptionConfig = | DynamoDbEncryptionConfig (

Expand Down Expand Up @@ -232,6 +249,13 @@ module {:extern "software.amazon.cryptography.dbencryptionsdk.dynamodb.internald
datatype DynamoDbTablesEncryptionConfig = | DynamoDbTablesEncryptionConfig (
nameonly tableEncryptionConfigs: DynamoDbTableEncryptionConfigList
)
datatype EncryptedDataKeyDescription = | EncryptedDataKeyDescription (
nameonly keyProviderId: string ,
nameonly keyProviderInfo: Option<string> := Option.None ,
nameonly branchKeyId: Option<string> := Option.None ,
nameonly branchKeyVersion: Option<string> := Option.None
)
type EncryptedDataKeyDescriptionList = seq<EncryptedDataKeyDescription>
datatype EncryptedPart = | EncryptedPart (
nameonly name: string ,
nameonly prefix: Prefix
Expand All @@ -246,6 +270,15 @@ module {:extern "software.amazon.cryptography.dbencryptionsdk.dynamodb.internald
datatype GetBranchKeyIdFromDdbKeyOutput = | GetBranchKeyIdFromDdbKeyOutput (
nameonly branchKeyId: string
)
datatype GetEncryptedDataKeyDescriptionInput = | GetEncryptedDataKeyDescriptionInput (
nameonly input: GetEncryptedDataKeyDescriptionUnion
)
datatype GetEncryptedDataKeyDescriptionOutput = | GetEncryptedDataKeyDescriptionOutput (
nameonly EncryptedDataKeyDescriptionOutput: EncryptedDataKeyDescriptionList
)
datatype GetEncryptedDataKeyDescriptionUnion =
| header(header: seq<uint8>)
| plaintextItem(plaintextItem: ComAmazonawsDynamodbTypes.AttributeMap)
datatype GetPrefix = | GetPrefix (
nameonly length: int32
)
Expand Down Expand Up @@ -510,6 +543,26 @@ abstract module AbstractAwsCryptographyDbEncryptionSdkDynamoDbService
History.CreateDynamoDbEncryptionBranchKeyIdSupplier := History.CreateDynamoDbEncryptionBranchKeyIdSupplier + [DafnyCallEvent(input, output)];
}

predicate GetEncryptedDataKeyDescriptionEnsuresPublicly(input: GetEncryptedDataKeyDescriptionInput , output: Result<GetEncryptedDataKeyDescriptionOutput, Error>)
{Operations.GetEncryptedDataKeyDescriptionEnsuresPublicly(input, output)}
// The public method to be called by library consumers
method GetEncryptedDataKeyDescription ( input: GetEncryptedDataKeyDescriptionInput )
returns (output: Result<GetEncryptedDataKeyDescriptionOutput, Error>)
requires
&& ValidState()
modifies Modifies - {History} ,
History`GetEncryptedDataKeyDescription
// Dafny will skip type parameters when generating a default decreases clause.
decreases Modifies - {History}
ensures
&& ValidState()
ensures GetEncryptedDataKeyDescriptionEnsuresPublicly(input, output)
ensures History.GetEncryptedDataKeyDescription == old(History.GetEncryptedDataKeyDescription) + [DafnyCallEvent(input, output)]
{
output := Operations.GetEncryptedDataKeyDescription(config, input);
History.GetEncryptedDataKeyDescription := History.GetEncryptedDataKeyDescription + [DafnyCallEvent(input, output)];
}

}
}
abstract module AbstractAwsCryptographyDbEncryptionSdkDynamoDbOperations {
Expand Down Expand Up @@ -541,4 +594,20 @@ abstract module AbstractAwsCryptographyDbEncryptionSdkDynamoDbOperations {
&& fresh(output.value.branchKeyIdSupplier)
&& fresh ( output.value.branchKeyIdSupplier.Modifies - ModifiesInternalConfig(config) - input.ddbKeyBranchKeyIdSupplier.Modifies ) )
ensures CreateDynamoDbEncryptionBranchKeyIdSupplierEnsuresPublicly(input, output)


predicate GetEncryptedDataKeyDescriptionEnsuresPublicly(input: GetEncryptedDataKeyDescriptionInput , output: Result<GetEncryptedDataKeyDescriptionOutput, Error>)
// The private method to be refined by the library developer


method GetEncryptedDataKeyDescription ( config: InternalConfig , input: GetEncryptedDataKeyDescriptionInput )
returns (output: Result<GetEncryptedDataKeyDescriptionOutput, Error>)
requires
&& ValidInternalConfig?(config)
modifies ModifiesInternalConfig(config)
// Dafny will skip type parameters when generating a default decreases clause.
decreases ModifiesInternalConfig(config)
ensures
&& ValidInternalConfig?(config)
ensures GetEncryptedDataKeyDescriptionEnsuresPublicly(input, output)
}
rishav-karanjit marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ use aws.cryptography.keyStore#KeyStore
use aws.cryptography.dbEncryptionSdk.structuredEncryption#CryptoAction

use com.amazonaws.dynamodb#DynamoDB_20120810
use com.amazonaws.dynamodb#AttributeMap
use com.amazonaws.dynamodb#TableName
use com.amazonaws.dynamodb#AttributeName
use com.amazonaws.dynamodb#Key
Expand All @@ -42,11 +43,59 @@ use aws.cryptography.materialProviders#AwsCryptographicMaterialProviders
]
)
service DynamoDbEncryption {
version: "2022-11-21",
operations: [ CreateDynamoDbEncryptionBranchKeyIdSupplier ],
version: "2024-04-02",
operations: [ CreateDynamoDbEncryptionBranchKeyIdSupplier, GetEncryptedDataKeyDescription],
errors: [ DynamoDbEncryptionException ]
}

operation GetEncryptedDataKeyDescription {
input: GetEncryptedDataKeyDescriptionInput,
output: GetEncryptedDataKeyDescriptionOutput,
}

structure GetEncryptedDataKeyDescriptionInput {
@required
input: GetEncryptedDataKeyDescriptionUnion
}

//= specification/dynamodb-encryption-client/ddb-get-encrypted-data-key-description.md#input
//= type=implication
//# This operation MUST take in either of the following:
//# - A binary [header](https://github.com/aws/aws-database-encryption-sdk-dynamodb/blob/main/specification/structured-encryption/header.md)
//# - A [encrypted DynamoDB item](https://github.com/aws/aws-database-encryption-sdk-dynamodb/blob/ff9f08a355a20c81540e4ca652e09aaeffe90c4b/specification/dynamodb-encryption-client/encrypt-item.md#encrypted-dynamodb-item)

union GetEncryptedDataKeyDescriptionUnion {
header: Blob,
plaintextItem: AttributeMap,
rishav-karanjit marked this conversation as resolved.
Show resolved Hide resolved
}

structure GetEncryptedDataKeyDescriptionOutput {
@required
EncryptedDataKeyDescriptionOutput: EncryptedDataKeyDescriptionList
}

list EncryptedDataKeyDescriptionList {
member: EncryptedDataKeyDescription
}

//= specification/dynamodb-encryption-client/ddb-get-encrypted-data-key-description.md#output
//= type=implication
//# This operation MUST return the following:
//# - [keyProviderId](https://github.com/aws/aws-database-encryption-sdk-dynamodb/blob/main/specification/structured-encryption/header.md#key-provider-id)
//#- [keyProviderInfo](https://github.com/aws/aws-database-encryption-sdk-dynamodb/blob/main/specification/structured-encryption/header.md#key-provider-information) (only for AWS Cryptographic Materials Provider Keyring)
//#- [branchKeyId](https://github.com/aws/aws-database-encryption-sdk-dynamodb/blob/main/specification/structured-encryption/header.md#key-provider-information) (only for hierarchy keyring)
//#- [branchKeyVersion](https://github.com/aws/aws-database-encryption-sdk-dynamodb/blob/main/specification/structured-encryption/header.md#key-provider-information) (only for hierarchy keyring)

structure EncryptedDataKeyDescription {
@required
keyProviderId: String,

keyProviderInfo: String,

branchKeyId: String,

branchKeyVersion: String
}
// The top level DynamoDbEncryption local service takes in no config
structure DynamoDbEncryptionConfig {
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,15 @@ include "DynamoDbEncryptionBranchKeyIdSupplier.dfy"

module AwsCryptographyDbEncryptionSdkDynamoDbOperations refines AbstractAwsCryptographyDbEncryptionSdkDynamoDbOperations {
import DynamoDbEncryptionBranchKeyIdSupplier
import EdkWrapping
import UUID
import AlgorithmSuites
import Header = StructuredEncryptionHeader
import opened DynamoDbEncryptionUtil

const SALT_LENGTH := 16
const IV_LENGTH := 12
const VERSION_LENGTH := 16

predicate ValidInternalConfig?(config: InternalConfig)
{true}
Expand Down Expand Up @@ -33,4 +42,72 @@ module AwsCryptographyDbEncryptionSdkDynamoDbOperations refines AbstractAwsCrypt
)
);
}
predicate GetEncryptedDataKeyDescriptionEnsuresPublicly(input: GetEncryptedDataKeyDescriptionInput , output: Result<GetEncryptedDataKeyDescriptionOutput, Error>)
{true}

method GetEncryptedDataKeyDescription(config: InternalConfig, input: GetEncryptedDataKeyDescriptionInput)
returns (output: Result<GetEncryptedDataKeyDescriptionOutput, Error>)
ensures GetEncryptedDataKeyDescriptionEnsuresPublicly(input, output)
{
var header;
match input.input
{
//= specification/dynamodb-encryption-client/ddb-get-encrypted-data-key-description.md#behavior
//# - If the input is a encrypted DynamoDB item, it MUST attempt to extract "aws_dbe_head" attribute from the DynamoDB item to get binary header.
case plaintextItem(plainTextItem) =>{
rishav-karanjit marked this conversation as resolved.
Show resolved Hide resolved
:- Need("aws_dbe_head" in plainTextItem && plainTextItem["aws_dbe_head"].B?, E("Header not found in the DynamoDB item."));
header := plainTextItem["aws_dbe_head"].B;
}
case header(headerItem) =>
header := headerItem;
}
//= specification/dynamodb-encryption-client/ddb-get-encrypted-data-key-description.md#behavior
//# - This operation MUST deserialize the header bytes according to the header format.
var deserializedHeader :- Header.PartialDeserialize(header).MapFailure(e => AwsCryptographyDbEncryptionSdkStructuredEncryption(e));
//= specification/dynamodb-encryption-client/ddb-get-encrypted-data-key-description.md#behavior
//# - This operation MUST extract the dataKeys from the deserialize header.
var datakeys := deserializedHeader.dataKeys;
var list : EncryptedDataKeyDescriptionList := [];
//= specification/dynamodb-encryption-client/ddb-get-encrypted-data-key-description.md#behavior
//# - For every Data Key in Data Keys, the operation MUST attempt to extract a description of the Data Key.
for i := 0 to |datakeys| {
var extractedKeyProviderId :- UTF8.Decode(datakeys[i].keyProviderId).MapFailure(e => E(e));
var extractedKeyProviderIdInfo:= Option.None;
var expectedBranchKeyVersion := Option.None;
if ("aws-kms" <= extractedKeyProviderId) {
:- Need(deserializedHeader.flavor == 0 || deserializedHeader.flavor == 1, E("Invalid format flavor."));
var algorithmSuite;
//= specification/dynamodb-encryption-client/ddb-get-encrypted-data-key-description.md#behavior
//# - This operation MUST extract the Format Flavor from the deserialize header.
if deserializedHeader.flavor == 0{
algorithmSuite := AlgorithmSuites.DBE_ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY_SYMSIG_HMAC_SHA384;
} else {
algorithmSuite := AlgorithmSuites.DBE_ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY_ECDSA_P384_SYMSIG_HMAC_SHA384;
}
var maybeKeyProviderIdInfo :- UTF8.Decode(datakeys[i].keyProviderInfo).MapFailure(e => E(e));
extractedKeyProviderIdInfo := Some(maybeKeyProviderIdInfo);
rishav-karanjit marked this conversation as resolved.
Show resolved Hide resolved
if extractedKeyProviderId == "aws-kms-hierarchy" {
var providerWrappedMaterial :- EdkWrapping.GetProviderWrappedMaterial(datakeys[i].ciphertext, algorithmSuite).MapFailure(e => AwsCryptographyMaterialProviders(e));
var EDK_CIPHERTEXT_BRANCH_KEY_VERSION_INDEX := SALT_LENGTH + IV_LENGTH;
var EDK_CIPHERTEXT_VERSION_INDEX := EDK_CIPHERTEXT_BRANCH_KEY_VERSION_INDEX + VERSION_LENGTH;
:- Need(EDK_CIPHERTEXT_BRANCH_KEY_VERSION_INDEX < EDK_CIPHERTEXT_VERSION_INDEX, E("Wrong branch key version index."));
:- Need(|providerWrappedMaterial| >= EDK_CIPHERTEXT_VERSION_INDEX, E("Incorrect ciphertext structure length."));
var branchKeyVersionUuid := providerWrappedMaterial[EDK_CIPHERTEXT_BRANCH_KEY_VERSION_INDEX .. EDK_CIPHERTEXT_VERSION_INDEX];
var maybeBranchKeyVersion :- UUID.FromByteArray(branchKeyVersionUuid).MapFailure(e => E(e));
expectedBranchKeyVersion := Some(maybeBranchKeyVersion);
}
}
var singleDataKeyOutput := EncryptedDataKeyDescription(
keyProviderId := extractedKeyProviderId,
keyProviderInfo := extractedKeyProviderIdInfo,
branchKeyId := extractedKeyProviderIdInfo,
branchKeyVersion := expectedBranchKeyVersion
);
list := list + [singleDataKeyOutput];
}

output := Success(GetEncryptedDataKeyDescriptionOutput(
EncryptedDataKeyDescriptionOutput := list
));
}
}
Loading
Loading