Skip to content

Commit 683a9dc

Browse files
author
Lucas McDonald
committed
Merge branch 'main' into python-poc
2 parents 6a8e8b6 + eb7679a commit 683a9dc

24 files changed

+767
-957
lines changed

DynamoDbEncryption/dafny/DynamoDbEncryption/src/AwsCryptographyDbEncryptionSdkDynamoDbOperations.dfy

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,11 @@ module AwsCryptographyDbEncryptionSdkDynamoDbOperations refines AbstractAwsCrypt
1010
import AlgorithmSuites
1111
import Header = StructuredEncryptionHeader
1212
import opened DynamoDbEncryptionUtil
13+
import opened StandardLibrary.MemoryMath
1314

14-
const SALT_LENGTH := 16
15-
const IV_LENGTH := 12
16-
const VERSION_LENGTH := 16
15+
const SALT_LENGTH : uint64 := 16
16+
const IV_LENGTH : uint64 := 12
17+
const VERSION_LENGTH : uint64 := 16
1718

1819
predicate ValidInternalConfig?(config: InternalConfig)
1920
{true}
@@ -70,7 +71,7 @@ module AwsCryptographyDbEncryptionSdkDynamoDbOperations refines AbstractAwsCrypt
7071
var list : EncryptedDataKeyDescriptionList := [];
7172
//= specification/dynamodb-encryption-client/ddb-get-encrypted-data-key-description.md#behavior
7273
//# - For every Data Key in Data Keys, the operation MUST attempt to extract a description of the Data Key.
73-
for i := 0 to |datakeys| {
74+
for i : uint64 := 0 to |datakeys| as uint64 {
7475
var extractedKeyProviderId :- UTF8.Decode(datakeys[i].keyProviderId).MapFailure(e => E(e));
7576
var extractedKeyProviderIdInfo:= Option.None;
7677
var expectedBranchKeyVersion := Option.None;
@@ -91,7 +92,8 @@ module AwsCryptographyDbEncryptionSdkDynamoDbOperations refines AbstractAwsCrypt
9192
var EDK_CIPHERTEXT_BRANCH_KEY_VERSION_INDEX := SALT_LENGTH + IV_LENGTH;
9293
var EDK_CIPHERTEXT_VERSION_INDEX := EDK_CIPHERTEXT_BRANCH_KEY_VERSION_INDEX + VERSION_LENGTH;
9394
:- Need(EDK_CIPHERTEXT_BRANCH_KEY_VERSION_INDEX < EDK_CIPHERTEXT_VERSION_INDEX, E("Wrong branch key version index."));
94-
:- Need(|providerWrappedMaterial| >= EDK_CIPHERTEXT_VERSION_INDEX, E("Incorrect ciphertext structure length."));
95+
SequenceIsSafeBecauseItIsInMemory(providerWrappedMaterial);
96+
:- Need(|providerWrappedMaterial| as uint64 >= EDK_CIPHERTEXT_VERSION_INDEX, E("Incorrect ciphertext structure length."));
9597
var branchKeyVersionUuid := providerWrappedMaterial[EDK_CIPHERTEXT_BRANCH_KEY_VERSION_INDEX .. EDK_CIPHERTEXT_VERSION_INDEX];
9698
var maybeBranchKeyVersion :- UUID.FromByteArray(branchKeyVersionUuid).MapFailure(e => E(e));
9799
expectedBranchKeyVersion := Some(maybeBranchKeyVersion);

DynamoDbEncryption/dafny/DynamoDbEncryption/src/ConfigToInfo.dfy

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ module SearchConfigToInfo {
2323
import opened DynamoDbEncryptionUtil
2424
import opened TermLoc
2525
import opened StandardLibrary.String
26+
import opened StandardLibrary.MemoryMath
2627
import MaterialProviders
2728
import SortedSets
2829

@@ -757,15 +758,15 @@ module SearchConfigToInfo {
757758
function method MakeDefaultConstructor(
758759
parts : seq<CB.BeaconPart>,
759760
ghost allParts : seq<CB.BeaconPart>,
760-
ghost numNon : nat,
761+
ghost numNon : uint64,
761762
converted : seq<CB.ConstructorPart> := []
762763
)
763764
: (ret : Result<seq<CB.Constructor>, Error>)
764765
requires 0 < |parts| + |converted|
765766
requires |allParts| == |parts| + |converted|
766767
requires parts == allParts[|converted|..]
767-
requires numNon <= |allParts|
768-
requires CB.OrderedParts(allParts, numNon)
768+
requires numNon as nat <= |allParts|
769+
requires CB.OrderedParts(allParts, numNon as nat)
769770
requires forall i | 0 <= i < |converted| ::
770771
&& converted[i].part == allParts[i]
771772
&& converted[i].required
@@ -776,7 +777,7 @@ module SearchConfigToInfo {
776777
//= type=implication
777778
//# * This default constructor MUST be all of the signed parts,
778779
//# followed by all the encrypted parts, all parts being required.
779-
&& CB.OrderedParts(allParts, numNon)
780+
&& CB.OrderedParts(allParts, numNon as nat)
780781
&& (forall i | 0 <= i < |ret.value[0].parts| ::
781782
&& ret.value[0].parts[i].part == allParts[i]
782783
&& ret.value[0].parts[i].required)
@@ -887,13 +888,13 @@ module SearchConfigToInfo {
887888
constructors : Option<ConstructorList>,
888889
name : string,
889890
parts : seq<CB.BeaconPart>,
890-
ghost numSigned : nat
891+
ghost numSigned : uint64
891892
)
892893
: (ret : Result<seq<CB.Constructor>, Error>)
893894
requires 0 < |parts|
894895
requires constructors.Some? ==> 0 < |constructors.value|
895-
requires numSigned <= |parts|
896-
requires CB.OrderedParts(parts, numSigned)
896+
requires numSigned as nat <= |parts|
897+
requires CB.OrderedParts(parts, numSigned as nat)
897898
ensures ret.Success? ==>
898899
&& (constructors.None? ==> |ret.value| == 1)
899900
&& (constructors.Some? ==> |ret.value| == |constructors.value|)
@@ -1065,10 +1066,11 @@ module SearchConfigToInfo {
10651066
:- Need(beacon.constructors.Some? || |signedParts| != 0 || |encryptedParts| != 0,
10661067
E("Compound beacon " + beacon.name + " defines no constructors, and also no local parts. Cannot make a default constructor from global parts."));
10671068

1068-
var numNon := |signed|;
1069-
assert CB.OrderedParts(signed, numNon);
1069+
SequenceIsSafeBecauseItIsInMemory(signed);
1070+
var numNon := |signed| as uint64;
1071+
assert CB.OrderedParts(signed, numNon as nat);
10701072
var allParts := signed + encrypted;
1071-
assert CB.OrderedParts(allParts, numNon);
1073+
assert CB.OrderedParts(allParts, numNon as nat);
10721074

10731075
var isSignedBeacon := |encrypted| == 0;
10741076
var _ :- BeaconNameAllowed(outer, virtualFields, beacon.name, "CompoundBeacon", isSignedBeacon);
@@ -1087,7 +1089,7 @@ module SearchConfigToInfo {
10871089
),
10881090
beacon.split[0],
10891091
allParts,
1090-
numNon,
1092+
numNon as nat,
10911093
constructors
10921094
)
10931095
}

DynamoDbEncryption/dafny/DynamoDbEncryption/src/DDBSupport.dfy

Lines changed: 43 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ module DynamoDBSupport {
1919
import opened Wrappers
2020
import opened StandardLibrary
2121
import opened StandardLibrary.UInt
22+
import opened StandardLibrary.MemoryMath
2223
import opened DynamoDbEncryptionUtil
2324
import opened DdbVirtualFields
2425
import opened SearchableEncryptionInfo
@@ -33,23 +34,30 @@ module DynamoDBSupport {
3334
// At the moment, this means that no attribute names starts with "aws_dbe_",
3435
// as all other attribute names would need to be configured, and all the
3536
// other weird constraints were checked at configuration time.
36-
function method IsWriteable(item : DDB.AttributeMap)
37-
: (ret : Result<bool, string>)
37+
method IsWriteable(item : DDB.AttributeMap)
38+
returns (ret : Result<bool, string>)
3839
//= specification/dynamodb-encryption-client/ddb-support.md#writable
3940
//= type=implication
4041
//# Writeable MUST reject any item containing an attribute which begins with `aws_dbe_`.
4142
ensures ret.Success? ==> forall k <- item :: !(ReservedPrefix <= k)
4243
{
43-
if forall k <- item :: !(ReservedPrefix <= k) then
44-
Success(true)
45-
else
46-
var bad := set k <- item | ReservedPrefix <= k;
47-
// We happen to order these values, but this ordering MUST NOT be relied upon.
48-
var badSeq := SortedSets.ComputeSetToOrderedSequence2(bad, CharLess);
49-
if |badSeq| == 0 then
50-
Failure("")
51-
else
52-
Failure("Writing reserved attributes not allowed : " + Join(badSeq, "\n"))
44+
var keys := SortedSets.ComputeSetToOrderedSequence2(item.Keys, CharLess);
45+
SequenceIsSafeBecauseItIsInMemory(keys);
46+
var rp := ReservedPrefix; // because the constant ReservedPrefix is actual an expensive function call
47+
for i : uint64 := 0 to |keys| as uint64
48+
invariant forall j | 0 <= j < i :: !(ReservedPrefix <= keys[j])
49+
{
50+
if rp <= keys[i] {
51+
var result := "Writing reserved attributes not allowed : ";
52+
for j : uint64 := i to |keys| as uint64 {
53+
if rp <= keys[i] {
54+
result := result + keys[i] + "\n";
55+
}
56+
}
57+
return Failure(result);
58+
}
59+
}
60+
return Success(true);
5361
}
5462

5563
function method GetEncryptedAttributes(
@@ -83,7 +91,8 @@ module DynamoDBSupport {
8391
{
8492
if expr.Some? then
8593
var attrs := GetEncryptedAttributes(actions, expr, attrNames);
86-
if |attrs| == 0 then
94+
SequenceIsSafeBecauseItIsInMemory(attrs);
95+
if |attrs| as uint64 == 0 then
8796
Success(true)
8897
else
8998
Failure("Condition Expressions forbidden on encrypted attributes : " + Join(attrs, ","))
@@ -121,7 +130,8 @@ module DynamoDBSupport {
121130
if expr.Some? then
122131
var attrs := Update.ExtractAttributes(expr.value, attrNames);
123132
var encryptedAttrs := Seq.Filter(s => IsSigned(actions, s), attrs);
124-
if |encryptedAttrs| == 0 then
133+
SequenceIsSafeBecauseItIsInMemory(encryptedAttrs);
134+
if |encryptedAttrs| as uint64 == 0 then
125135
Success(true)
126136
else
127137
Failure("Update Expressions forbidden on signed attributes : " + Join(encryptedAttrs, ","))
@@ -169,11 +179,13 @@ module DynamoDBSupport {
169179
//# if the constructed compound beacon does not match
170180
//# the existing attribute value AddSignedBeacons MUST fail.
171181
var badAttrs := set k <- newAttrs | k in item && item[k] != newAttrs[k] :: k;
172-
:- Need(|badAttrs| == 0, E("Signed beacons have generated values different from supplied values."));
182+
SetIsSafeBecauseItIsInMemory(badAttrs);
183+
:- Need(|badAttrs| as uint64 == 0, E("Signed beacons have generated values different from supplied values."));
173184
var version : DDB.AttributeMap := map[VersionTag := DS(" ")];
174185
var both := newAttrs.Keys * item.Keys;
175186
var bad := set k <- both | newAttrs[k] != item[k];
176-
if 0 < |bad| {
187+
SetIsSafeBecauseItIsInMemory(bad);
188+
if 0 < |bad| as uint64 {
177189
// We happen to order these values, but this ordering MUST NOT be relied upon.
178190
var badSeq := SortedSets.ComputeSetToOrderedSequence2(bad, CharLess);
179191
return Failure(E("Supplied Beacons do not match calculated beacons : " + Join(badSeq, ", ")));
@@ -254,7 +266,8 @@ module DynamoDBSupport {
254266
req.FilterExpression,
255267
req.ExpressionAttributeNames,
256268
req.ExpressionAttributeValues);
257-
:- Need(|newItems| < INT32_MAX_LIMIT, DynamoDbEncryptionUtil.E("This is impossible."));
269+
SequenceIsSafeBecauseItIsInMemory(newItems);
270+
:- Need(|newItems| as uint64 < INT32_MAX_LIMIT as uint64, DynamoDbEncryptionUtil.E("This is impossible."));
258271
var trimmedItems := Seq.Map(i => DoRemoveBeacons(i), newItems);
259272
var count :=
260273
if resp.Count.Some? then
@@ -323,7 +336,8 @@ module DynamoDBSupport {
323336
req.FilterExpression,
324337
req.ExpressionAttributeNames,
325338
req.ExpressionAttributeValues);
326-
:- Need(|newItems| < INT32_MAX_LIMIT, DynamoDbEncryptionUtil.E("This is impossible."));
339+
SequenceIsSafeBecauseItIsInMemory(newItems);
340+
:- Need(|newItems| as uint64 < INT32_MAX_LIMIT as uint64, DynamoDbEncryptionUtil.E("This is impossible."));
327341
var trimmedItems := Seq.Map(i => DoRemoveBeacons(i), newItems);
328342
var count :=
329343
if resp.Count.Some? then
@@ -344,14 +358,15 @@ module DynamoDBSupport {
344358
requires forall x <- results :: x in bv.virtualFields
345359
ensures output.Success? ==> forall x <- output.value :: x in bv.virtualFields
346360
{
347-
if |fields| == 0 then
361+
SequenceIsSafeBecauseItIsInMemory(fields);
362+
if |fields| as uint64 == 0 then
348363
Success(results)
349364
else
350-
var optValue :- GetVirtField(bv.virtualFields[fields[0]], item);
365+
var optValue :- GetVirtField(bv.virtualFields[fields[0 as uint32]], item);
351366
if optValue.Some? then
352-
GetVirtualFieldsLoop(fields[1..], bv, item, results[fields[0] := optValue.value])
367+
GetVirtualFieldsLoop(fields[1 as uint32..], bv, item, results[fields[0 as uint32] := optValue.value])
353368
else
354-
GetVirtualFieldsLoop(fields[1..], bv, item, results)
369+
GetVirtualFieldsLoop(fields[1 as uint32..], bv, item, results)
355370
}
356371

357372
method GetVirtualFields(beaconVersion : SearchableEncryptionInfo.BeaconVersion, item : DDB.AttributeMap)
@@ -371,18 +386,19 @@ module DynamoDBSupport {
371386
requires forall x <- results :: x in bv.beacons
372387
ensures output.Success? ==> forall x <- output.value :: x in bv.beacons
373388
{
374-
if |fields| == 0 then
389+
SequenceIsSafeBecauseItIsInMemory(fields);
390+
if |fields| as uint64 == 0 then
375391
Success(results)
376392
else
377-
var beacon := bv.beacons[fields[0]];
393+
var beacon := bv.beacons[fields[0 as uint32]];
378394
if beacon.Compound? then
379395
var optValue :- beacon.cmp.getNaked(item, bv.virtualFields);
380396
if optValue.Some? then
381-
GetCompoundBeaconsLoop(fields[1..], bv, item, results[fields[0] := optValue.value])
397+
GetCompoundBeaconsLoop(fields[1 as uint32..], bv, item, results[fields[0] := optValue.value])
382398
else
383-
GetCompoundBeaconsLoop(fields[1..], bv, item, results)
399+
GetCompoundBeaconsLoop(fields[1 as uint32..], bv, item, results)
384400
else
385-
GetCompoundBeaconsLoop(fields[1..], bv, item, results)
401+
GetCompoundBeaconsLoop(fields[1 as uint32..], bv, item, results)
386402
}
387403

388404
method GetCompoundBeacons(beaconVersion : SearchableEncryptionInfo.BeaconVersion, item : DDB.AttributeMap)

0 commit comments

Comments
 (0)