@@ -28,7 +28,6 @@ module {:options "-functionSyntax:4"} DdbEncryptionTestVectors {
28
28
import JSON. API
29
29
import opened JSONHelpers
30
30
import Norm = DynamoDbNormalizeNumber
31
-
32
31
import Types = AwsCryptographyDbEncryptionSdkDynamoDbTypes
33
32
import DDB = ComAmazonawsDynamodbTypes
34
33
import Filter = DynamoDBFilterExpr
@@ -37,10 +36,15 @@ module {:options "-functionSyntax:4"} DdbEncryptionTestVectors {
37
36
import KeyMaterial
38
37
import UTF8
39
38
import KeyVectorsTypes = AwsCryptographyMaterialProvidersTestVectorKeysTypes
39
+ import CMP = AwsCryptographyMaterialProvidersTypes
40
40
import KeyVectors
41
41
import CreateInterceptedDDBClient
42
42
import SortedSets
43
43
import Seq
44
+ import SI = SearchableEncryptionInfo
45
+ import MaterialProviders
46
+ import MPT = AwsCryptographyMaterialProvidersTypes
47
+ import Aws. Cryptography. Primitives
44
48
45
49
predicate IsValidInt32 (x: int ) { - 0x8000_0000 <= x < 0x8000_0000}
46
50
type ConfigName = string
@@ -121,7 +125,8 @@ module {:options "-functionSyntax:4"} DdbEncryptionTestVectors {
121
125
configsForModTest : PairList ,
122
126
writeTests : seq <WriteTest >,
123
127
roundTripTests : seq <RoundTripTest >,
124
- decryptTests : seq <DecryptTest >
128
+ decryptTests : seq <DecryptTest >,
129
+ strings : seq <string >
125
130
) {
126
131
127
132
method RunAllTests ()
@@ -137,13 +142,15 @@ module {:options "-functionSyntax:4"} DdbEncryptionTestVectors {
137
142
print |ioTests|, " ioTests. \n";
138
143
print |configsForIoTest|, " configsForIoTest. \n";
139
144
print |configsForModTest|, " configsForModTest. \n";
145
+ print |strings|, " strings. \n";
140
146
if |roundTripTests| != 0 {
141
147
print |roundTripTests[0]. configs|, " configs and ", |roundTripTests[0]. records|, " records for round trip. \n";
142
148
}
143
149
if |roundTripTests| > 1 {
144
150
print |roundTripTests[1]. configs|, " configs and ", |roundTripTests[1]. records|, " records for round trip. \n";
145
151
}
146
152
Validate ();
153
+ StringOrdering ();
147
154
BasicIoTest ();
148
155
RunIoTests ();
149
156
BasicQueryTest ();
@@ -156,6 +163,35 @@ module {:options "-functionSyntax:4"} DdbEncryptionTestVectors {
156
163
DeleteTable (client);
157
164
}
158
165
166
+ function NewOrderRecord (i : nat , str : string ) : Record
167
+ {
168
+ var n := String. Base10Int2String (i);
169
+ var m : DDB. AttributeMap := map [HashName := DDB. AttributeValue. N (n), "StrValue" := DDB. AttributeValue. S (str)];
170
+ Record (i, m)
171
+ }
172
+
173
+ method StringOrdering () {
174
+ print "StringOrdering\n";
175
+ var client :- expect CreateInterceptedDDBClient. CreateVanillaDDBClient ();
176
+ var records : seq < Record> := [];
177
+ for i := 0 to |strings| {
178
+ records := records + [NewOrderRecord (i, strings[i])];
179
+ }
180
+ WriteAllRecords (client, records);
181
+ var subRecords := Seq. Map ((r : Record ) => r. item, records);
182
+ var ops := ["< ", "<= ", "> ", ">= ", "=", "<> "];
183
+ for i := 0 to |strings| {
184
+ for j := 0 to |ops| {
185
+ var expr := Some ("StrValue " + ops[j] + " :val ");
186
+ var vals := Some (map[":val " := DDB.AttributeValue.S(strings[i])]);
187
+ var query := SimpleQuery (None, None, expr, []);
188
+ var items1 := FullScan (client, query, Some(map[]), vals);
189
+ var bv :- expect GetFakeBeaconVersion ();
190
+ var items2 :- expect Filter. FilterResults (bv, subRecords, None, expr, None, vals);
191
+ CompareRecordsDisordered2 (items1, items2);
192
+ }
193
+ }
194
+ }
159
195
160
196
method Validate () {
161
197
var bad := false ;
@@ -531,7 +567,11 @@ module {:options "-functionSyntax:4"} DdbEncryptionTestVectors {
531
567
}
532
568
}
533
569
534
- method OneRoundTripTest (client : DDB .IDynamoDBClient, record : Record ) {
570
+ method OneRoundTripTest (client : DDB .IDynamoDBClient, record : Record )
571
+ requires client. ValidState ()
572
+ ensures client. ValidState ()
573
+ modifies client. Modifies
574
+ {
535
575
var putInput := DDB. PutItemInput (
536
576
TableName := TableName,
537
577
Item := record.item,
@@ -545,7 +585,7 @@ module {:options "-functionSyntax:4"} DdbEncryptionTestVectors {
545
585
ExpressionAttributeValues := None
546
586
);
547
587
var _ :- expect client. PutItem (putInput);
548
-
588
+ expect HashName in record . item;
549
589
var getInput := DDB. GetItemInput (
550
590
TableName := TableName,
551
591
Key := map[HashName := record.item[HashName]],
@@ -772,6 +812,19 @@ module {:options "-functionSyntax:4"} DdbEncryptionTestVectors {
772
812
}
773
813
expect ! bad;
774
814
}
815
+ method CompareRecordsDisordered2 (expected : DDB .ItemList, actual : DDB .ItemList)
816
+ {
817
+ expect |expected| == |actual|;
818
+ var bad := false ;
819
+ for i := 0 to |expected| {
820
+ var found := FindMatchingRecord (expected[i], actual);
821
+ if ! found {
822
+ print "Did not find result for record ", expected[i], "\n";
823
+ bad := true ;
824
+ }
825
+ }
826
+ expect ! bad;
827
+ }
775
828
776
829
method BasicIoTestScan (client : DDB .IDynamoDBClient, records : seq <Record >)
777
830
requires client. ValidState ()
@@ -863,9 +916,11 @@ module {:options "-functionSyntax:4"} DdbEncryptionTestVectors {
863
916
var asSet := Seq. ToSet (s);
864
917
DDB. AttributeValue. BS (SortedSets.ComputeSetToOrderedSequence2(asSet, ByteLess))
865
918
case L (list) =>
866
- DDB. AttributeValue. L (Seq.Map(n => Normalize(n), list))
919
+ // for some reason, Seq.Map() fails for verify, even when revealed
920
+ var value := seq (|list|, i requires 0 <= i < |list| => Normalize(list[i]));
921
+ DDB. AttributeValue. L (value)
867
922
case M (m) =>
868
- DDB. AttributeValue. M (map k <- m :: k := Normalize(m[k]))
923
+ DDB. AttributeValue. M (map k <- m :: k := Normalize(m[k]))
869
924
case _ => value
870
925
}
871
926
}
@@ -1047,7 +1102,7 @@ module {:options "-functionSyntax:4"} DdbEncryptionTestVectors {
1047
1102
1048
1103
function MakeEmptyTestVector () : TestVectorConfig
1049
1104
{
1050
- TestVectorConfig (MakeCreateTableInput(), [], map [], [], map [], map [], [], [], [], [], [], [], [], [])
1105
+ TestVectorConfig (MakeCreateTableInput(), [], map [], [], map [], map [], [], [], [], [], [], [], [], [], [] )
1051
1106
}
1052
1107
1053
1108
method ParseTestVector (data : JSON , prev : TestVectorConfig ) returns (output : Result< TestVectorConfig, string > )
@@ -1067,6 +1122,7 @@ module {:options "-functionSyntax:4"} DdbEncryptionTestVectors {
1067
1122
var writeTests : seq < WriteTest> := [];
1068
1123
var roundTripTests : seq < RoundTripTest> := [];
1069
1124
var decryptTests : seq < DecryptTest> := [];
1125
+ var strings : seq < string > := [];
1070
1126
1071
1127
for i := 0 to |data. obj| {
1072
1128
match data. obj[i]. 0 {
@@ -1084,6 +1140,7 @@ module {:options "-functionSyntax:4"} DdbEncryptionTestVectors {
1084
1140
case "WriteTests" => writeTests :- GetWriteTests (data.obj[i].1);
1085
1141
case "RoundTripTest" => roundTripTests :- GetRoundTripTests (data.obj[i].1);
1086
1142
case "DecryptTests" => decryptTests :- GetDecryptTests (data.obj[i].1);
1143
+ case "Strings" => strings :- GetStrings (data.obj[i].1);
1087
1144
case _ => return Failure ("Unexpected top level tag " + data.obj[i].0);
1088
1145
}
1089
1146
}
@@ -1104,7 +1161,8 @@ module {:options "-functionSyntax:4"} DdbEncryptionTestVectors {
1104
1161
configsForModTest := prev.configsForModTest + queryPairs,
1105
1162
writeTests := prev.writeTests + writeTests,
1106
1163
roundTripTests := prev.roundTripTests + roundTripTests,
1107
- decryptTests := prev.decryptTests + decryptTests
1164
+ decryptTests := prev.decryptTests + decryptTests,
1165
+ strings := prev.strings + strings
1108
1166
)
1109
1167
);
1110
1168
}
@@ -1207,6 +1265,10 @@ module {:options "-functionSyntax:4"} DdbEncryptionTestVectors {
1207
1265
method GetOneTableConfig (name : string , data : JSON ) returns (output : Result< TableConfig, string > )
1208
1266
{
1209
1267
:- Need (data.Object?, "A Table Config must be an object.");
1268
+ var logicalTableName := TableName;
1269
+ var partitionKeyName : DDB. KeySchemaAttributeName := HashName;
1270
+ var sortKeyName : Option< DDB. KeySchemaAttributeName> := None;
1271
+ var algorithmSuiteId : Option< CMP. DBEAlgorithmSuiteId> := None;
1210
1272
var encrypt : seq < string > := [];
1211
1273
var attributeActionsOnEncrypt : Types. AttributeActions := map [];
1212
1274
var allowed : seq < DDB. AttributeName> := [];
@@ -1216,13 +1278,47 @@ module {:options "-functionSyntax:4"} DdbEncryptionTestVectors {
1216
1278
var virtualFields : seq < Types. VirtualField> := [];
1217
1279
var keySource : Option< Types. BeaconKeySource> := None;
1218
1280
var search : Option< Types. SearchConfig> := None;
1281
+ var legacyOverride: Option< Types. LegacyOverride> := None;
1282
+ var plaintextOverride: Option< Types. PlaintextOverride> := None;
1219
1283
1220
1284
for i := 0 to |data. obj| {
1221
1285
var obj := data. obj[i];
1222
1286
match obj. 0 {
1287
+ case "logicalTableName" =>
1288
+ :- Need (obj.1.String?, "logicalTableName must be of type String.");
1289
+ logicalTableName := obj. 1. str;
1290
+ case "partitionKeyName" =>
1291
+ :- Need (obj.1.String?, "partitionKeyName must be of type String.");
1292
+ :- Need (DDB.IsValid_KeySchemaAttributeName(obj.1.str), "partitionKeyName '" + obj. 1. str + "' is not a valid KeySchemaAttributeName. ");
1293
+ partitionKeyName := obj. 1. str;
1294
+ case "sortKeyName" =>
1295
+ :- Need (obj.1.String?, "sortKeyName must be of type String.");
1296
+ :- Need (DDB.IsValid_KeySchemaAttributeName(obj.1.str), "sortKeyName '" + obj. 1. str + "' is not a valid KeySchemaAttributeName. ");
1297
+ sortKeyName := Some (obj.1.str);
1298
+ case "algorithmSuiteId" =>
1299
+ :- Need (obj.1.String?, "algorithmSuiteId must be of type String.");
1300
+ if obj. 1. str == "ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY_SYMSIG_HMAC_SHA384" {
1301
+ algorithmSuiteId := Some (CMP.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY_SYMSIG_HMAC_SHA384);
1302
+ } else if obj. 1. str == "ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY_ECDSA_P384_SYMSIG_HMAC_SHA384" {
1303
+ algorithmSuiteId := Some (CMP.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY_ECDSA_P384_SYMSIG_HMAC_SHA384);
1304
+ } else {
1305
+ return Failure ("algorithmSuiteId '" + obj.1.str + "' must be either ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY_SYMSIG_HMAC_SHA384 or ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY_ECDSA_P384_SYMSIG_HMAC_SHA384");
1306
+ }
1307
+ case "plaintextOverride" =>
1308
+ :- Need (obj.1.String?, "plaintextOverride must be of type String.");
1309
+ if obj. 1. str == "FORCE_PLAINTEXT_WRITE_ALLOW_PLAINTEXT_READ" {
1310
+ plaintextOverride := Some (Types.FORCE_PLAINTEXT_WRITE_ALLOW_PLAINTEXT_READ);
1311
+ } else if obj. 1. str == "FORBID_PLAINTEXT_WRITE_ALLOW_PLAINTEXT_READ" {
1312
+ plaintextOverride := Some (Types.FORBID_PLAINTEXT_WRITE_ALLOW_PLAINTEXT_READ);
1313
+ } else if obj. 1. str == "FORBID_PLAINTEXT_WRITE_FORBID_PLAINTEXT_READ" {
1314
+ plaintextOverride := Some (Types.FORBID_PLAINTEXT_WRITE_FORBID_PLAINTEXT_READ);
1315
+ } else {
1316
+ return Failure ("plaintextOverride '" + obj.1.str + "' must be one of FORCE_PLAINTEXT_WRITE_ALLOW_PLAINTEXT_READ, FORBID_PLAINTEXT_WRITE_ALLOW_PLAINTEXT_READ or FORBID_PLAINTEXT_WRITE_FORBID_PLAINTEXT_READ");
1317
+ }
1318
+
1223
1319
case "attributeActionsOnEncrypt" => attributeActionsOnEncrypt :- GetAttributeActions (obj.1);
1224
1320
case "allowedUnsignedAttributePrefix" =>
1225
- :- Need (obj.1.String?, "Prefix must be of type String.");
1321
+ :- Need (obj.1.String?, "allowedUnsignedAttributePrefix must be of type String.");
1226
1322
prefix := obj. 1. str;
1227
1323
case "allowedUnsignedAttributes" => allowed :- GetAttrNames (obj.1);
1228
1324
case "search" => var src :- GetOneSearchConfig (obj.1); search := Some (src);
@@ -1242,18 +1338,18 @@ module {:options "-functionSyntax:4"} DdbEncryptionTestVectors {
1242
1338
1243
1339
var config :=
1244
1340
Types. DynamoDbTableEncryptionConfig (
1245
- logicalTableName := TableName ,
1246
- partitionKeyName := HashName ,
1247
- sortKeyName := None ,
1341
+ logicalTableName := logicalTableName ,
1342
+ partitionKeyName := partitionKeyName ,
1343
+ sortKeyName := sortKeyName ,
1248
1344
search := search,
1249
1345
attributeActionsOnEncrypt := attributeActionsOnEncrypt,
1250
1346
allowedUnsignedAttributes := OptSeq(allowed),
1251
1347
allowedUnsignedAttributePrefix := OptSeq (prefix),
1252
- algorithmSuiteId := None ,
1348
+ algorithmSuiteId := algorithmSuiteId ,
1253
1349
keyring := Some (keyring),
1254
1350
cmm := None,
1255
- legacyOverride := None ,
1256
- plaintextOverride := None
1351
+ legacyOverride := legacyOverride ,
1352
+ plaintextOverride := plaintextOverride
1257
1353
);
1258
1354
return Success (TableConfig(name, config, |data.obj| == 0));
1259
1355
}
@@ -1327,6 +1423,32 @@ module {:options "-functionSyntax:4"} DdbEncryptionTestVectors {
1327
1423
);
1328
1424
}
1329
1425
1426
+ method GetFakeBeaconVersion () returns (output : Result< SI. BeaconVersion, string > )
1427
+ ensures output. Success? ==> output. value. ValidState () && fresh (output. value. Modifies ())
1428
+ {
1429
+ var keyMaterial : KeyMaterial. KeyMaterial :=
1430
+ KeyMaterial. StaticKeyStoreInformation ("abc", UTF8.EncodeAscii("abc"), [1,2,3,4,5], [1,2,3,4,5]);
1431
+ var store := SKS. CreateStaticKeyStore (keyMaterial);
1432
+ var source : Types. BeaconKeySource := Types. single (Types.SingleKeyStore(keyId := "foo", cacheTTL := 42));
1433
+
1434
+ var sb := Types. StandardBeacon (name := "name", length := 5 as Types.BeaconBitLength, loc := None, style := None);
1435
+
1436
+ var mpl :- expect MaterialProviders. MaterialProviders ();
1437
+
1438
+ var cacheType : MPT. CacheType := MPT. Default (Default := MPT.DefaultCache(entryCapacity := 1));
1439
+
1440
+ var input := MPT. CreateCryptographicMaterialsCacheInput (
1441
+ cache := cacheType
1442
+ );
1443
+ var cache :- expect mpl. CreateCryptographicMaterialsCache (input);
1444
+
1445
+ var client :- expect Primitives. AtomicPrimitives ();
1446
+ var src := SI. KeySource (client, store, SI.SingleLoc("foo"), cache, 100 as uint32);
1447
+
1448
+ var bv :- expect SI. MakeBeaconVersion (1, src, map[], map[], map[]);
1449
+ return Success (bv);
1450
+ }
1451
+
1330
1452
method GetAttributeActions (data : JSON ) returns (output : Result< Types. AttributeActions, string > )
1331
1453
{
1332
1454
:- Need (data.Object?, "attributeActionsOnEncrypt must be an object");
0 commit comments