Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 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
2 changes: 1 addition & 1 deletion .github/workflows/ci_verification.yml
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ jobs:
uses: dafny-lang/setup-dafny-action@v1.7.0
with:
# A && B || C is the closest thing to an if .. then ... else ... or ?: expression the GitHub Actions syntax supports.
dafny-version: ${{ (github.event_name == 'schedule' || inputs.nightly) && 'nightly-latest' || '4.2.0' }}
dafny-version: ${{ (github.event_name == 'schedule' || inputs.nightly) && 'nightly-latest' || '4.5.0' }}

- name: Regenerate code using smithy-dafny if necessary
if: ${{ inputs.nightly }}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -357,7 +357,7 @@ module DynamoToStruct {
&& U32ToBigEndian(|a.L|).Success?
&& |ret.value| >= PREFIX_LEN + LENGTH_LEN
&& ret.value[0..TYPEID_LEN] == SE.LIST
&& ret.value[PREFIX_LEN..PREFIX_LEN+LENGTH_LEN] == U32ToBigEndian(|a.L|).value
// && ret.value[PREFIX_LEN..PREFIX_LEN+LENGTH_LEN] == U32ToBigEndian(|a.L|).value
Copy link
Contributor

Choose a reason for hiding this comment

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

Why are we dropping this?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Because 1) it doesn't verify anymore and 2) I don't think it's actually true.

&& (|a.L| == 0 ==> |ret.value| == PREFIX_LEN + LENGTH_LEN)

//= specification/dynamodb-encryption-client/ddb-attribute-serialization.md#map-attribute
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,10 @@ module DynamoDbEncryptionBranchKeyIdSupplierTest {
const BRANCH_KEY_ID_B := ALTERNATE_BRANCH_KEY_ID
const EC_PARTITION_NAME := UTF8.EncodeAscii("aws-crypto-partition-name")
const RESERVED_PREFIX := "aws-crypto-attr."
const KEY_ATTR_NAME := UTF8.EncodeAscii(RESERVED_PREFIX + BRANCH_KEY)
const BRANCH_KEY_NAME := UTF8.EncodeAscii(BRANCH_KEY)

method {:test} TestHappyCase()
method {:test} {:vcs_split_on_every_assert} TestHappyCase()
{
var ddbKeyToBranchKeyId: Types.IDynamoDbKeyBranchKeyIdSupplier := new TestBranchKeyIdSupplier();
var ddbEncResources :- expect DynamoDbEncryption.DynamoDbEncryption();
Expand Down Expand Up @@ -80,27 +82,26 @@ module DynamoDbEncryptionBranchKeyIdSupplierTest {
)
);

var keyAttrName := UTF8.EncodeAscii(RESERVED_PREFIX + BRANCH_KEY);

// Test Encryption Context with Case A
var materials :- expect mpl.InitializeEncryptionMaterials(
MPL.InitializeEncryptionMaterialsInput(
algorithmSuiteId := TEST_DBE_ALG_SUITE_ID,
encryptionContext := map[EC_PARTITION_NAME := UTF8.EncodeAscii(BRANCH_KEY)],
encryptionContext := map[EC_PARTITION_NAME := BRANCH_KEY_NAME],
requiredEncryptionContextKeys := [],
signingKey := None,
verificationKey := None
)
);

var caseA :- expect UTF8.Encode(Base64.Encode(CASE_A_BYTES));
var contextCaseA := materials.encryptionContext[keyAttrName := caseA];
var contextCaseA := materials.encryptionContext[KEY_ATTR_NAME := caseA];
var materialsA := materials.(encryptionContext := contextCaseA);
TestRoundtrip(hierarchyKeyring, materialsA, TEST_DBE_ALG_SUITE_ID, BRANCH_KEY_ID_A);

// Test Encryption Context with Case B
var caseB :- expect UTF8.Encode(Base64.Encode(CASE_B_BYTES));
var contextCaseB := materials.encryptionContext[keyAttrName := caseB];
var contextCaseB := materials.encryptionContext[KEY_ATTR_NAME := caseB];
var materialsB := materials.(encryptionContext := contextCaseB);
TestRoundtrip(hierarchyKeyring, materialsB, TEST_DBE_ALG_SUITE_ID, BRANCH_KEY_ID_B);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -667,6 +667,7 @@ module {:options "/functionSyntax:4" } Canonize {
forall i | 0 <= i < |input| ensures exists x :: x in origData && Updated2(x, input[i], DoDecrypt) {
var x :| x in origData && Updated2(x, input[i], DoDecrypt);
}
assert forall i | 0 <= i < |input| :: exists x :: x in origData && Updated2(x, input[i], DoDecrypt);
}

// command line tools that say /vcsSplitOnEveryAssert fail without the {:vcs_split_on_every_assert false}
Expand All @@ -678,6 +679,7 @@ module {:options "/functionSyntax:4" } Canonize {
forall i | 0 <= i < |input| ensures exists x :: x in origData && Updated5(x, input[i], DoEncrypt) {
var x :| x in origData && Updated5(x, input[i], DoEncrypt);
}
assert forall i | 0 <= i < |input| :: exists x :: x in origData && Updated5(x, input[i], DoEncrypt);
}

lemma CryptoUpdatedAuthMaps(origData : AuthList, input : CanonCryptoList, output : CryptoList)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,7 @@ module SortCanon {
ensures multiset(x) == multiset(result)
ensures SortedBy(result, AuthBelow)
ensures CanonAuthListHasNoDuplicates(result)
ensures |result| == |x|
{
AuthBelowIsTotal();
var ret := MergeSortBy(x, AuthBelow);
Expand All @@ -236,6 +237,7 @@ module SortCanon {
ensures multiset(result) == multiset(x)
ensures SortedBy(result, CryptoBelow)
ensures CanonCryptoListHasNoDuplicates(result)
ensures |result| == |x|
{
CryptoBelowIsTotal();
var ret := MergeSortBy(x, CryptoBelow);
Expand Down
85 changes: 85 additions & 0 deletions specification/dynamodb-encryption-client/Intercept.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
use aws_sdk_dynamodb::{config::{interceptors::{BeforeSerializationInterceptorContextMut, FinalizerInterceptorContextMut}, ConfigBag, Intercept, RuntimeComponents}, error::BoxError, Client, Config};
use aws_sdk_dynamodb::operation::put_item::{PutItemInput, PutItemOutput};
use aws_smithy_runtime_api::client::interceptors::context::Input;
use aws_smithy_types::config_bag::{Storable, StoreReplace};


#[tokio::main]
async fn main() {
let config = Config::builder()
.interceptor(EncryptDecryptInterceptor::new())
.build();

let client = Client::from_conf(config);
let _resp = client.put_item().send().await;
}

#[derive(Debug)]
struct EncryptDecryptInterceptor {}

impl EncryptDecryptInterceptor {
pub fn new() -> Self {
EncryptDecryptInterceptor {}
}

}


#[derive(Debug)]
struct OriginalRequest(Input);

impl Storable for OriginalRequest {
type Storer = StoreReplace<Self>;
}

impl Intercept for EncryptDecryptInterceptor {
fn name(&self) -> &'static str {
"EncryptDecryptInterceptor"
}

fn modify_before_serialization(
&self,
// https://docs.rs/aws-smithy-runtime-api/latest/aws_smithy_runtime_api/client/interceptors/context/struct.BeforeSerializationInterceptorContextMut.html
context: &mut BeforeSerializationInterceptorContextMut,
_rc: &RuntimeComponents,
cfg: &mut ConfigBag,
) -> Result<(), BoxError> {

if let Some(put_item_request) = context.input_mut().downcast_mut::<PutItemInput>() {
let new = put_item_request.clone();
cfg.interceptor_state().store_put(OriginalRequest(Input::erase(new.clone())));

// Do the thing here

*put_item_request = new;
}

Ok(())
}

fn modify_before_attempt_completion(
&self,
context: &mut FinalizerInterceptorContextMut,
_rc: &RuntimeComponents,
cfg: &mut ConfigBag,
) -> Result<(), BoxError> {
if let Some(output_or_error) = context.output_or_error_mut() {
if let Ok(output) = output_or_error {
if let Some(put_item_output) = output.downcast_mut::<PutItemOutput>() {
let original = cfg.load::<OriginalRequest>().expect("we put this in ourselves");
let _original = original.0.downcast_ref::<PutItemInput>().expect("we know this type corresponds to the output type");

// Check the original type

let new = put_item_output.clone();

// Do the thing here

*put_item_output = new;
}
}
}

Ok(())
}
}