@@ -114,16 +114,16 @@ module AwsCryptographyDbEncryptionSdkStructuredEncryptionOperations refines Abst
114
114
function method {:opaque} GetBinary (data : AuthList , path : Path ): (result: Result< StructuredDataTerminal, Error> )
115
115
ensures result. Success? ==> exists x :: x in data && x. key == path
116
116
{
117
- var data := FindAuth (data, path);
117
+ var pos := FindAuth (data, path);
118
118
119
- if data . None? then
119
+ if pos . None? then
120
120
Failure (E("The field name " + Paths.PathToString(path) + " is required. "))
121
- else if data. value. data. typeId != BYTES_TYPE_ID then
121
+ else if data[pos . value] . data. typeId != BYTES_TYPE_ID then
122
122
Failure (E(Paths.PathToString(path) + " must be a binary Terminal. "))
123
- else if data. value. action != DO_NOT_SIGN then
123
+ else if data[pos . value] . action != DO_NOT_SIGN then
124
124
Failure (E(Paths.PathToString(path) + " must be DO_NOT_SIGN. "))
125
125
else
126
- Success (data.value.data)
126
+ Success (data[pos .value] .data)
127
127
}
128
128
129
129
// Return the sum of the sizes of the given fields
@@ -269,35 +269,84 @@ module AwsCryptographyDbEncryptionSdkStructuredEncryptionOperations refines Abst
269
269
output := GetV2EncryptionContext2 (contextAttrs);
270
270
}
271
271
272
- function method {:opaque} Find (haystack : CryptoList , needle : Path ) : Result< CryptoItem, Error>
272
+ function {:opaque} Find (haystack : CryptoList , needle : Path , start : nat := 0) : (res : Result< nat , Error> )
273
+ requires start <= |haystack|
274
+ requires forall i | 0 <= i < start :: haystack[i]. key != needle
275
+ ensures (exists x <- haystack :: x .key == needle) <= => res. Success?
276
+ ensures (forall x <- haystack :: x .key != needle) <= => res. Failure?
277
+ ensures (forall x <- haystack :: x .key != needle) <= => res == Failure (E("Not Found"))
278
+ ensures res. Success? ==>
279
+ && 0 <= res. value < |haystack|
280
+ && haystack[res. value]. key == needle
281
+ && (forall i | 0 <= i < res. value :: haystack[i]. key != needle)
282
+ decreases |haystack| - start
273
283
{
274
- if |haystack| == 0 then
284
+ if |haystack| == start then
275
285
Failure (E("Not Found"))
276
- else if haystack[0 ]. key == needle
277
- then Success (haystack[0] )
286
+ else if haystack[start ]. key == needle then
287
+ Success (start )
278
288
else
279
- Find (haystack[1..], needle)
289
+ Find (haystack, needle, start + 1)
290
+ }
291
+ by method {
292
+ for i := 0 to |haystack|
293
+ invariant forall x < - haystack[.. i] :: x. key != needle
294
+ {
295
+ if haystack[i]. key == needle {
296
+ return Success (i);
297
+ }
298
+ }
299
+ return Failure (E("Not Found"));
280
300
}
281
301
282
- function method {:opaque} FindAuth (haystack : AuthList , needle : Path ) : (result : Option< AuthItem> )
283
- ensures result. Some? ==> exists x :: x in haystack && x. key == needle
302
+ function {:opaque} FindAuth (haystack : AuthList , needle : Path , start : nat := 0) : (res : Option< nat > )
303
+ requires start <= |haystack|
304
+ requires forall i | 0 <= i < start :: haystack[i]. key != needle
305
+ ensures (exists x <- haystack :: x .key == needle) <= => res. Some?
306
+ ensures (forall x <- haystack :: x .key != needle) <= => res == None
307
+ ensures res. Some? ==>
308
+ && 0 <= res. value < |haystack|
309
+ && haystack[res. value]. key == needle
310
+ && (forall i | 0 <= i < res. value :: haystack[i]. key != needle)
311
+ decreases |haystack| - start
284
312
{
285
- if |haystack| == 0 then
313
+ if |haystack| == start then
286
314
None
287
- else if haystack[0 ]. key == needle
288
- then Some (haystack[0] )
315
+ else if haystack[start ]. key == needle then
316
+ Some (start )
289
317
else
290
- FindAuth (haystack[1..], needle)
318
+ FindAuth (haystack, needle, start + 1)
319
+ }
320
+ by method {
321
+ for i := 0 to |haystack|
322
+ invariant forall x < - haystack[.. i] :: x. key != needle
323
+ {
324
+ if haystack[i]. key == needle {
325
+ return Some (i);
326
+ }
327
+ }
328
+ return None;
291
329
}
292
330
293
- function method {:opaque} CountEncrypted (list : CanonCryptoList ) : nat
331
+ function {:opaque} CountEncrypted (list : CanonCryptoList ) : nat
294
332
{
295
333
if |list| == 0 then
296
334
0
297
335
else if list[0]. action == ENCRYPT_AND_SIGN then
298
336
1 + CountEncrypted (list[1..])
299
337
else
300
338
CountEncrypted (list[1..])
339
+ } by method {
340
+ reveal CountEncrypted ();
341
+ var result : nat := 0;
342
+ for i := |list| downto 0
343
+ invariant result == CountEncrypted (list[i..])
344
+ {
345
+ if list[i]. action == ENCRYPT_AND_SIGN {
346
+ result := result + 1;
347
+ }
348
+ }
349
+ return result;
301
350
}
302
351
303
352
method {:vcs_split_on_every_assert} GetV2EncryptionContext2 (fields : CryptoList )
@@ -355,7 +404,7 @@ module AwsCryptographyDbEncryptionSdkStructuredEncryptionOperations refines Abst
355
404
var fieldUtf8 := keys[i];
356
405
var fieldStr := fieldMap[fieldUtf8];
357
406
var item :- Find (fields, fieldMap[fieldUtf8]);
358
- var attr : StructuredDataTerminal := item. data;
407
+ var attr : StructuredDataTerminal := fields[ item] . data;
359
408
var attrStr : ValidUTF8Bytes;
360
409
var legendChar : char ;
361
410
if attr. typeId == NULL {
@@ -395,34 +444,33 @@ module AwsCryptographyDbEncryptionSdkStructuredEncryptionOperations refines Abst
395
444
keys : seq <string >,
396
445
plaintextStructure: StructuredDataMap ,
397
446
cryptoSchema: CryptoSchemaMap ,
398
- ghost origKeys : seq < string > := keys ,
447
+ pos : nat := 0 ,
399
448
acc : CryptoList := []
400
449
)
401
450
: (ret : Result< CryptoList, Error> )
451
+ requires 0 <= pos <= |keys|
452
+ requires |acc| == pos
402
453
requires forall k < - keys :: k in plaintextStructure
403
454
requires forall k < - keys :: k in cryptoSchema
404
455
requires forall k < - acc :: |k. key| == 1
405
- requires CryptoListHasNoDuplicates (acc)
406
- requires |acc| + |keys| == |origKeys|
407
- requires keys == origKeys[|acc|.. ]
408
- requires forall i | 0 <= i < |acc| :: acc[i]. key == Paths. StringToUniPath (origKeys[i])
456
+ requires forall i | 0 <= i < |acc| :: acc[i]. key == Paths. StringToUniPath (keys[i])
409
457
requires Seq. HasNoDuplicates (keys)
410
- requires Seq . HasNoDuplicates (origKeys)
458
+ decreases |keys| - pos
411
459
412
460
ensures ret. Success? ==>
413
461
&& (forall k < - ret. value :: |k. key| == 1)
414
462
&& CryptoListHasNoDuplicates (ret.value)
415
463
{
416
464
reveal Seq. HasNoDuplicates ();
417
465
Paths. StringToUniPathUnique ();
418
- if |keys| == 0 then
466
+ if |keys| == pos then
419
467
Success (acc)
420
468
else
421
- var key := keys[0 ];
469
+ var key := keys[pos ];
422
470
var path := Paths. StringToUniPath (key);
423
471
var item := CryptoItem (key := path, data := plaintextStructure[key], action := cryptoSchema[key]);
424
472
var newAcc := acc + [item];
425
- BuildCryptoMap2 (keys[1..] , plaintextStructure, cryptoSchema, origKeys , newAcc)
473
+ BuildCryptoMap2 (keys, plaintextStructure, cryptoSchema, pos+1 , newAcc)
426
474
}
427
475
428
476
function method BuildCryptoMap (plaintextStructure: StructuredDataMap , cryptoSchema: CryptoSchemaMap ) :
@@ -440,33 +488,33 @@ module AwsCryptographyDbEncryptionSdkStructuredEncryptionOperations refines Abst
440
488
keys : seq <string >,
441
489
plaintextStructure: StructuredDataMap ,
442
490
authSchema: AuthenticateSchemaMap ,
443
- ghost origKeys : seq < string > := keys ,
491
+ pos : nat := 0 ,
444
492
acc : AuthList := []
445
493
)
446
494
: (ret : Result< AuthList, Error> )
495
+ requires 0 <= pos <= |keys|
496
+ requires |acc| == pos
447
497
requires forall k < - keys :: k in plaintextStructure
448
498
requires forall k < - keys :: k in authSchema
449
499
requires forall k < - acc :: |k. key| == 1
500
+ requires forall i | 0 <= i < |acc| :: acc[i]. key == Paths. StringToUniPath (keys[i])
450
501
requires AuthListHasNoDuplicates (acc)
451
- requires |acc| + |keys| == |origKeys|
452
- requires keys == origKeys[|acc|.. ]
453
- requires forall i | 0 <= i < |acc| :: acc[i]. key == Paths. StringToUniPath (origKeys[i])
454
502
requires Seq. HasNoDuplicates (keys)
455
- requires Seq . HasNoDuplicates (origKeys)
503
+ decreases |keys| - pos
456
504
457
505
ensures ret. Success? ==>
458
506
&& (forall k < - ret. value :: |k. key| == 1)
459
507
&& AuthListHasNoDuplicates (ret.value)
460
508
{
461
509
reveal Seq. HasNoDuplicates ();
462
- if |keys| == 0 then
510
+ if |keys| == pos then
463
511
Success (acc)
464
512
else
465
- var key := keys[0 ];
513
+ var key := keys[pos ];
466
514
var path := Paths. StringToUniPath (key);
467
515
var item := AuthItem (key := path, data := plaintextStructure[key], action := authSchema[key]);
468
516
var newAcc := acc + [item];
469
- BuildAuthMap2 (keys[1..] , plaintextStructure, authSchema, origKeys , newAcc)
517
+ BuildAuthMap2 (keys, plaintextStructure, authSchema, pos+1 , newAcc)
470
518
}
471
519
472
520
function method BuildAuthMap (plaintextStructure: StructuredDataMap , authSchema: AuthenticateSchemaMap )
@@ -480,24 +528,28 @@ module AwsCryptographyDbEncryptionSdkStructuredEncryptionOperations refines Abst
480
528
BuildAuthMap2 (keys, plaintextStructure, authSchema)
481
529
}
482
530
483
- function method UnBuildCryptoMap (list : CryptoList , dataSoFar : StructuredDataMap := map[], actionsSoFar : CryptoSchemaMap := map[]) :
531
+ function method {:tailrecursion} UnBuildCryptoMap (list : CryptoList , pos : nat := 0 , dataSoFar : StructuredDataMap := map[], actionsSoFar : CryptoSchemaMap := map[]) :
484
532
(res : Result< (StructuredDataMap, CryptoSchemaMap), Error> )
533
+ requires 0 <= pos <= |list|
534
+ requires |dataSoFar| == pos
535
+ requires |actionsSoFar| <= pos
485
536
requires forall k < - actionsSoFar :: k in dataSoFar
486
537
requires (forall v :: v in actionsSoFar.Values ==> IsAuthAttr(v))
487
538
requires forall k < - list :: |k. key| == 1
539
+ decreases |list| - pos
488
540
ensures res. Success? ==>
489
541
&& (forall k < - res. value. 1 :: k in res. value. 0)
490
542
&& (forall v :: v in res. value. 1. Values ==> IsAuthAttr (v))
491
543
{
492
- if |list| == 0 then
544
+ if |list| == pos then
493
545
Success ((dataSoFar, actionsSoFar))
494
546
else
495
- var key :- Paths. UniPathToString (list[0 ].key);
547
+ var key :- Paths. UniPathToString (list[pos ].key);
496
548
:- Need (key !in dataSoFar, E("Duplicate Key " + key));
497
- if IsAuthAttr (list[0 ].action) then
498
- UnBuildCryptoMap (list[1..] , dataSoFar[key := list[0 ].data], actionsSoFar[key := list[0 ].action])
549
+ if IsAuthAttr (list[pos ].action) then
550
+ UnBuildCryptoMap (list, pos+1 , dataSoFar[key := list[pos ].data], actionsSoFar[key := list[pos ].action])
499
551
else
500
- UnBuildCryptoMap (list[1..] , dataSoFar[key := list[0 ].data], actionsSoFar)
552
+ UnBuildCryptoMap (list, pos+1 , dataSoFar[key := list[pos ].data], actionsSoFar)
501
553
}
502
554
503
555
lemma EncryptStructureOutputHasSinglePaths (origData : CryptoList , finalData : CryptoList )
0 commit comments