Skip to content

Commit 403dfac

Browse files
authored
fix: issue when a DynamoDB Set attribute is marked as SIGN_ONLY in th… (#560)
* fix: issue when a DynamoDB Set attribute is marked as SIGN_ONLY in the AWS Database Encryption SDK (DB-ESDK) for DynamoDB. DB-ESDK for DynamoDB supports SIGN_ONLY and ENCRYPT_AND_SIGN attribute actions. In version 3.1.0 and below, when a Set type is assigned a SIGN_ONLY attribute action, there is a chance that signature validation of the record containing a Set will fail on read, even if the Set attributes contain the same values. The probability of a failure depends on the order of the elements in the Set combined with how DynamoDB returns this data, which is undefined. This update addresses the issue by ensuring that any Set values are canonicalized in the same order while written to DynamoDB as when read back from DynamoDB. See: https://github.com/aws/aws-database-encryption-sdk-dynamodb-java/DecryptWithPermute/README.md for additional details
1 parent a331844 commit 403dfac

File tree

59 files changed

+6290
-57
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

59 files changed

+6290
-57
lines changed

.github/workflows/ci_permute_java.yml

+85
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
# This workflow performs tests in Java.
2+
name: Library Java tests
3+
4+
on:
5+
pull_request:
6+
push:
7+
branches:
8+
- main
9+
workflow_dispatch:
10+
# Manual trigger for this workflow, either the normal version
11+
# or the nightly build that uses the latest Dafny prerelease
12+
# (accordingly to the "nightly" parameter).
13+
inputs:
14+
nightly:
15+
description: 'Run the nightly build'
16+
required: false
17+
type: boolean
18+
schedule:
19+
# Nightly build against Dafny's nightly prereleases,
20+
# for early warning of verification issues or regressions.
21+
# Timing chosen to be adequately after Dafny's own nightly build,
22+
# but this might need to be tweaked:
23+
# https://github.com/dafny-lang/dafny/blob/master/.github/workflows/deep-tests.yml#L16
24+
- cron: "30 16 * * *"
25+
26+
jobs:
27+
testJava:
28+
# Don't run the nightly build on forks
29+
if: github.event_name != 'schedule' || github.repository_owner == 'aws'
30+
strategy:
31+
matrix:
32+
library: [
33+
DecryptWithPermute
34+
]
35+
java-version: [ 8, 11, 16, 17 ]
36+
os: [
37+
# TODO just test on mac for now
38+
#windows-latest,
39+
#ubuntu-latest,
40+
macos-latest
41+
]
42+
runs-on: ${{ matrix.os }}
43+
permissions:
44+
id-token: write
45+
contents: read
46+
steps:
47+
- name: Configure AWS Credentials
48+
uses: aws-actions/configure-aws-credentials@v2
49+
with:
50+
aws-region: us-west-2
51+
role-to-assume: arn:aws:iam::370957321024:role/GitHub-CI-DDBEC-Dafny-Role-us-west-2
52+
role-session-name: DDBEC-Dafny-Java-Tests
53+
54+
- uses: actions/checkout@v3
55+
with:
56+
submodules: recursive
57+
58+
- name: Setup Dafny
59+
uses: dafny-lang/[email protected]
60+
with:
61+
# A && B || C is the closest thing to an if .. then ... else ... or ?: expression the GitHub Actions syntax supports.
62+
dafny-version: ${{ (github.event_name == 'schedule' || inputs.nightly) && 'nightly-latest' || '4.1.0' }}
63+
64+
- name: Setup Java ${{ matrix.java-version }}
65+
uses: actions/setup-java@v3
66+
with:
67+
distribution: 'corretto'
68+
java-version: ${{ matrix.java-version }}
69+
70+
- name: Build ${{ matrix.library }} implementation
71+
shell: bash
72+
working-directory: ./${{ matrix.library }}
73+
run: |
74+
# This works because `node` is installed by default on GHA runners
75+
CORES=$(node -e 'console.log(os.cpus().length)')
76+
make build_java CORES=$CORES
77+
78+
- name: Test ${{ matrix.library }}
79+
working-directory: ./${{ matrix.library }}
80+
run: |
81+
# Clear MPL from cache
82+
# We have to do this because MakeFile does not do this yet. The MakeFile automatically builds and deploys dependencies
83+
# instead it should be picking it up from Maven.
84+
rm -rf ~/.m2/repository/software/amazon/cryptography/aws-cryptographic-material-providers
85+
make test_java

CHANGELOG.md

+13
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,18 @@
11
# Changelog
22

3+
## 3.1.1 2023-11-07
4+
5+
### Fix
6+
7+
Issue when a DynamoDB Set attribute is marked as SIGN_ONLY in the AWS Database Encryption SDK (DB-ESDK) for DynamoDB.
8+
9+
DB-ESDK for DynamoDB supports SIGN_ONLY and ENCRYPT_AND_SIGN attribute actions. In version 3.1.0 and below, when a Set type is assigned a SIGN_ONLY attribute action, there is a chance that signature validation of the record containing a Set will fail on read, even if the Set attributes contain the same values. The probability of a failure depends on the order of the elements in the Set combined with how DynamoDB returns this data, which is undefined.
10+
11+
This update addresses the issue by ensuring that any Set values are canonicalized in the same order while written to DynamoDB as when read back from DynamoDB.
12+
13+
See: https://github.com/aws/aws-database-encryption-sdk-dynamodb-java/DecryptWithPermute/README.md for additional details
14+
15+
316
## 3.1.0 2023-09-07
417

518
### Features

DecryptWithPermute/.gitignore

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
TestResults
2+
ImplementationFromDafny.cs
3+
TestsFromDafny.cs
4+
**/bin
5+
**/obj

DecryptWithPermute/Makefile

+53
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
CORES=2
5+
6+
include ../SharedMakefile.mk
7+
8+
DIR_STRUCTURE_V2=V2
9+
10+
PROJECT_SERVICES := DecryptWithPermute
11+
12+
# Namespace for each local service
13+
# Currently our build relies on local services and namespaces being 1:1
14+
SERVICE_NAMESPACE_DecryptWithPermute=aws.cryptography.dbEncryptionSdk.decryptWithPermute
15+
16+
MAX_RESOURCE_COUNT=20000000
17+
# Order is important
18+
# In java they MUST be built
19+
# in the order they depend on each other
20+
PROJECT_DEPENDENCIES := \
21+
submodules/MaterialProviders/AwsCryptographyPrimitives \
22+
submodules/MaterialProviders/ComAmazonawsKms \
23+
submodules/MaterialProviders/ComAmazonawsDynamodb \
24+
submodules/MaterialProviders/AwsCryptographicMaterialProviders \
25+
DynamoDbEncryption
26+
27+
STD_LIBRARY=submodules/MaterialProviders/StandardLibrary
28+
SMITHY_DEPS=submodules/MaterialProviders/model
29+
30+
# Since we are packaging projects differently, we cannot make assumptions
31+
# about where the files are located.
32+
# This is here to get unblocked but should be removed once we have migrated packages
33+
# to the new packaging format.
34+
PROJECT_INDEX := \
35+
submodules/MaterialProviders/AwsCryptographyPrimitives/src/Index.dfy \
36+
submodules/MaterialProviders/ComAmazonawsKms/src/Index.dfy \
37+
submodules/MaterialProviders/ComAmazonawsDynamodb/src/Index.dfy \
38+
submodules/MaterialProviders/AwsCryptographicMaterialProviders/dafny/AwsCryptographicMaterialProviders/src/Index.dfy \
39+
submodules/MaterialProviders/AwsCryptographicMaterialProviders/dafny/AwsCryptographyKeyStore/src/Index.dfy
40+
41+
# Dependencies for each local service
42+
SERVICE_DEPS_DecryptWithPermute := \
43+
submodules/MaterialProviders/AwsCryptographyPrimitives \
44+
submodules/MaterialProviders/ComAmazonawsKms \
45+
submodules/MaterialProviders/ComAmazonawsDynamodb \
46+
submodules/MaterialProviders/AwsCryptographicMaterialProviders/dafny/AwsCryptographicMaterialProviders \
47+
submodules/MaterialProviders/AwsCryptographicMaterialProviders/dafny/AwsCryptographyKeyStore \
48+
DynamoDbEncryption/dafny/DynamoDbEncryption \
49+
DynamoDbEncryption/dafny/StructuredEncryption \
50+
DynamoDbEncryption/dafny/DynamoDbItemEncryptor
51+
52+
format_net:
53+
pushd runtimes/net && dotnet format DynamoDbEncryption.csproj && popd

DecryptWithPermute/README.md

+170
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,170 @@
1+
## DecryptWithPermute
2+
3+
DB-ESDK for DynamoDB supports SIGN_ONLY and ENCRYPT_AND_SIGN attribute actions.
4+
In version 3.1.0 and below, when a Set type is assigned a SIGN_ONLY attribute action,
5+
there is a chance that signature validation of the record containing a Set will fail on read,
6+
even if the Set attributes contain the same values.
7+
The probability of a failure depends on the order of the elements in the Set
8+
combined with how DynamoDB returns this data, which is undefined.
9+
10+
The 3.1.1 update addresses the issue by ensuring that any Set values are canonicalized
11+
in the same order while written to DynamoDB as when read back from DynamoDB.
12+
13+
This project implements a slightly modified version of DecryptItem
14+
from the the AWS Database Encryption SDK for DynamoDB,
15+
which can validate an encrypted record that as written with 3.1.0,
16+
allowing it to be decrypted.
17+
18+
PermuteDecrypt is exactly like the DynamoDbItemEncryptor's DecryptItem,
19+
with one exception :
20+
If the signature fails to match, and SIGN_ONLY Sets are involved,
21+
then other permutations of the members of those sets are tried,
22+
and the item is decrypted if any of those permutations allow the signature to match.
23+
24+
If you would normally decrypt an item like this
25+
```
26+
DynamoDbItemEncryptor itemEncryptor = DynamoDbItemEncryptor.builder()
27+
.DynamoDbItemEncryptorConfig(config)
28+
.build();
29+
DecryptItemOutput decryptedItem = itemEncryptor.DecryptItem(myInput);
30+
```
31+
You instead do this :
32+
```
33+
DynamoDbPermuteDecryptor itemDecryptor = DynamoDbPermuteDecryptor.builder()
34+
.DynamoDbPermuteDecryptorConfig.builder()
35+
.inner(config)
36+
.build()
37+
.build();
38+
PermuteDecryptOutput decryptedItem = itemDecryptor.PermuteDecrypt(
39+
PermuteDecryptInput.builder()
40+
.inner(myInput),
41+
.maxSetSize(7)
42+
.build()
43+
.build();
44+
```
45+
The PermuteDecryptInput holds a normal DecryptItemInput object, plus a `maxSetSize`.
46+
If any set in the item has more elements than `maxSetSize`,
47+
decryption of the item is attempted, but no permutations are attempted.
48+
49+
The output of PermuteDecrypt holds two entries
50+
`inner` : a DecryptItemOutput object
51+
`didPermute` : if false, the item was validated and decrypted with no special handling.
52+
If true, some permutation of sets in the input allowed successful validation.
53+
54+
If you think you know the set permutations with which the item was originally written,
55+
set that attribute of your item to the expected permutation, and call `PermuteDecrypt`
56+
with a `maxSetSize` of `1`. A single attempt will be made to validate and decrypt the record,
57+
which will quickly succeed or fail.
58+
59+
To exhaustively try every permutation of a set of size N required N! (N factorial) attempts.
60+
As sets get large (over 7 or 8) this can start to take a considerable amount of time,
61+
so use `maxSetSize` to put a limit on the size of a set that will be attempted.
62+
A set as large as 9 can probably be handled, depending on your hardware,
63+
but over that is probably untenable.
64+
65+
66+
### Code Organization
67+
68+
DecryptWithPermute is a project containing the following Dafny 'localServices' under `dafny`:
69+
- DecryptWithPermute: A single entry point : PermuteDecrypt described above.
70+
71+
Currently this project only supports Java.
72+
73+
#### Java
74+
75+
`runtimes/java` contains the Java related code and build instructions for this project.
76+
77+
Within `runtimes/java`:
78+
79+
- `src/main/java` contains all hand written Java code, including externs.
80+
- `src/main/dafny-generated` contains all Dafny to Java transpiled code.
81+
- `src/main/smithy-generated` contains all Smithy to Java generated code.
82+
83+
### Development
84+
85+
Common Makefile targets are:
86+
87+
- `make verify` verifies the whole project. You should specify a `CORES` that is as high as your
88+
computer supports in order to speed this up. However, this will still probably take long enough
89+
that your dev loop should instead use the following:
90+
- You can instead specify a single service to verify via: `make verify_service SERVICE=DecryptWithPermute`
91+
- You can also verify a specific file and output in a more help format via: `make verify_single FILE=<filename>`,
92+
where `<filename>` is the path to the file to verify relative to this directory (`DynamoDbEncryption`).
93+
You may optionally narrow down the scope by specifying a `PROC`. For example, if you just want to verify
94+
the method `EncryptStructure`, use `make verify_single FILE=<filename> PROC=EncryptStructure`
95+
- `make build_java` transpiles, builds, and tests everything from scratch in Java.
96+
You will need to run this the first time you clone this repo, and any time you introduce changes
97+
that end up adding or removing dafny-generated files.
98+
- The above command takes a while to complete.
99+
If you want to re-generate dafny code specific to a service for a service, use the following:
100+
`make local_transpile_impl_java_single SERVICE=DecryptWithPermute FILE=Index.dfy`
101+
and then `test_java` to build/test those changes.
102+
Using `Index.dfy` will end up transpiling the entire service, but you can also specify a different
103+
file to scope down the transpilation further. This target will transpile `FILE` and every
104+
"includes" in that `FILE`, recursively down to the bounds of the service namespace.
105+
Note that the `transpile_implementation_java_single` target is provided as a convenience,
106+
and is not guaranteed to be 100% consistent with output from the regular `build_java` target.
107+
The behavior SHOULD NOT be different, although if you are experiencing
108+
weird behavior, see if `build_java` resolves the issue.
109+
Only use this target for local testing.
110+
- `make local_transpile_test_java_single SERVICE=DecryptWithPermute FILE=Validate.dfy`
111+
may be used similar to above in order to re-transpile a specific test file
112+
(and any of that module's "includes" within `/test`).
113+
Note that this will clobber all other Dafny generated tests being run
114+
with `make test_java`. This target is useful to quickly iterate on changes
115+
to tests within a specific file, but you will need to `make build_java`
116+
again if you want to run the full test suite locally.
117+
Only use this target for local testing.
118+
- `make test_java` builds and tests the transpiled code in Java.
119+
120+
### Development Requirements
121+
122+
* Dafny 4.1.0: https://github.com/dafny-lang/dafny
123+
* A Java 8 or newer development environment
124+
125+
#### (Optional) Dafny Report Generator Requirements
126+
127+
Optionally, if you want to run the [Dafny Report Generator](#generate-dafny-report)
128+
you will need to install the `dafny-reportgenerator` dotnet tool
129+
(and make sure `.dotnet/tools` is within your `PATH`,
130+
see instructions in the output from running the following command):
131+
132+
```
133+
dotnet tool install --global dafny-reportgenerator --version 1.2.0
134+
```
135+
136+
#### (Optional) Duvet Requirements
137+
138+
Optionally, if you want to run [Duvet](https://github.com/awslabs/duvet) reports,
139+
you will need to use Cargo to install duvet.
140+
141+
If you don't have it already,
142+
[get and install Cargo and Rust](https://doc.rust-lang.org/cargo/getting-started/installation.html).
143+
144+
Then install duvet:
145+
146+
```
147+
cargo +stable install duvet
148+
```
149+
150+
#### System Dependencies - macOS only
151+
152+
If you are using macOS then you must install OpenSSL 1.1,
153+
and the OpenSSL 1.1 `lib` directory must be on the dynamic linker path at runtime.
154+
155+
If the .NET runtime cannot locate your OpenSSL 1.1 libraries,
156+
you may encounter an error that says:
157+
158+
> No usable version of libssl was found
159+
160+
To resolve this,
161+
we recommend that you install OpenSSL via Homebrew using `brew install [email protected]`.
162+
163+
## Security
164+
165+
See [CONTRIBUTING](CONTRIBUTING.md#security-issue-notifications) for more information.
166+
167+
## License
168+
169+
This project is licensed under the Apache-2.0 License.
170+

0 commit comments

Comments
 (0)