Skip to content
Closed
Show file tree
Hide file tree
Changes from all 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 buildspec.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ phases:
# Although Dafny does have releases, we often need a newer hash than the latest release, while still needing the
# the security of reproducible builds.
- cd dafny
- git reset --hard df707bc07e3c39390286dfd0c1576d0a3f556f8b
- git reset --hard 4a98e283d5608cd7bd623be2b90f96a1d9eb557b
- cd ..
- nuget restore dafny/Source/Dafny.sln
- msbuild dafny/Source/Dafny.sln
Expand Down
3 changes: 1 addition & 2 deletions src/Crypto/RSAEncryption.dfy
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,7 @@ module {:extern "RSAEncryption"} RSAEncryption {
newtype {:nativeType "int", "number"} StrengthBits = x | 81 <= x < (0x8000_0000) witness 81

// This trait represents the parent for RSA public and private keys
trait {:termination false} Key {
ghost var Repr: set<object>
trait {:termination false} Key extends Validatable {
ghost const strength: StrengthBits
ghost const padding: PaddingMode
const pem: seq<uint8>
Expand Down
14 changes: 4 additions & 10 deletions src/KMS/KMSUtils.dfy
Original file line number Diff line number Diff line change
Expand Up @@ -120,12 +120,7 @@ module {:extern "KMSUtils"} KMSUtils {

method {:extern "KMSUtils.ClientHelper", "AddCachingClientCallback"} AddCachingClientCallback(client: IAmazonKeyManagementService, region: Option<string>, cache: CachingClientSupplierCache)

trait {:extern "DafnyAWSKMSClientSupplier"} DafnyAWSKMSClientSupplier {
ghost var Repr: set<object>

predicate Valid()
reads this, Repr
ensures Valid() ==> this in Repr
trait {:extern "DafnyAWSKMSClientSupplier"} DafnyAWSKMSClientSupplier extends Validatable {

method GetClient(region: Option<string>) returns (res: Result<IAmazonKeyManagementService>)
requires Valid()
Expand Down Expand Up @@ -227,8 +222,7 @@ module {:extern "KMSUtils"} KMSUtils {
}
}

class CachingClientSupplierCache {
ghost var Repr: set<object>
class CachingClientSupplierCache extends Validatable {
var ClientCache: map<Option<string>, IAmazonKeyManagementService>

predicate Valid()
Expand Down Expand Up @@ -276,8 +270,8 @@ module {:extern "KMSUtils"} KMSUtils {
ensures Valid() ==> this in Repr
{
this in Repr &&
clientSupplier in Repr && clientSupplier.Repr <= Repr && this !in clientSupplier.Repr && clientSupplier.Valid() &&
clientCache in Repr && clientCache.Repr <= Repr && this !in clientCache.Repr && clientCache.Valid() &&
ValidComponent(clientSupplier) &&
ValidComponent(clientCache) &&
clientSupplier.Repr !! clientCache.Repr
}

Expand Down
19 changes: 9 additions & 10 deletions src/SDK/CMM/CachingCMM.dfy
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,8 @@ module {:extern "CachingCMMDef"} CachingCMMDef {
ensures Valid() ==> this in Repr
{
this in Repr &&
cmm in Repr && cmm.Repr <= Repr && this !in cmm.Repr && cmm.Valid() &&
cmc in Repr && cmc.Repr <= Repr && this !in cmc.Repr && cmc.Valid() &&
ValidComponent(cmm) &&
ValidComponent(cmc) &&
cmm.Repr !! cmc.Repr
}

Expand Down Expand Up @@ -144,7 +144,7 @@ module {:extern "CachingCMMDef"} CachingCMMDef {
returns (res: Result<Materials.ValidEncryptionMaterials>)
requires Valid()
modifies Repr
ensures Valid() && fresh(Repr - old(Repr))
ensures ValidAndFresh()
ensures res.Success? ==> res.value.Serializable()
{
if materialsRequest.plaintextLength.None?
Expand Down Expand Up @@ -199,7 +199,7 @@ module {:extern "CachingCMMDef"} CachingCMMDef {
returns (res: Result<Materials.ValidDecryptionMaterials>)
requires Valid()
modifies Repr
ensures Valid() && fresh(Repr - old(Repr))
ensures ValidAndFresh()
ensures res.Success? ==> res.value.plaintextDataKey.Some?
{
var isSerializable := EncryptionContext.CheckSerializable(materialsRequest.encryptionContext);
Expand Down Expand Up @@ -295,8 +295,7 @@ module {:extern "CachingCMMDef"} CachingCMMDef {
res := Digest.Digest(CACHE_ID_HASH_ALGORITHM, wr.GetDataWritten());
}

class CryptographicMaterialsCache {
ghost var Repr: set<object>
class CryptographicMaterialsCache extends Validatable {
// The cache is split up into two independent maps, one for the encrypt path and one for the decrypt path.
var EncryptMap: map<seq<uint8>, CacheEntryEncrypt>
var DecryptMap: map<seq<uint8>, CacheEntryDecrypt>
Expand Down Expand Up @@ -338,7 +337,7 @@ module {:extern "CachingCMMDef"} CachingCMMDef {
requires Valid()
requires encMat.Serializable()
modifies Repr
ensures Valid() && fresh(Repr - old(Repr)) && entry in Repr
ensures ValidAndFresh() && entry in Repr
{
entry := new CacheEntryEncrypt(encMat, secondsToLiveLimit);
Repr := Repr + {entry};
Expand All @@ -351,7 +350,7 @@ module {:extern "CachingCMMDef"} CachingCMMDef {
requires Valid()
requires decMat.plaintextDataKey.Some?
modifies Repr
ensures Valid() && fresh(Repr - old(Repr)) && entry in Repr
ensures ValidAndFresh() && entry in Repr
{
entry := new CacheEntryDecrypt(decMat, secondsToLiveLimit);
Repr := Repr + {entry};
Expand All @@ -362,7 +361,7 @@ module {:extern "CachingCMMDef"} CachingCMMDef {
method EvictEncrypt(cacheID: seq<uint8>)
requires Valid()
modifies Repr
ensures Valid() && fresh(Repr - old(Repr))
ensures ValidAndFresh()
{
EncryptMap := map id | id in EncryptMap.Keys && id != cacheID :: EncryptMap[id];
}
Expand All @@ -371,7 +370,7 @@ module {:extern "CachingCMMDef"} CachingCMMDef {
method EvictDecrypt(cacheID: seq<uint8>)
requires Valid()
modifies Repr
ensures Valid() && fresh(Repr - old(Repr))
ensures ValidAndFresh()
{
DecryptMap := map id | id in DecryptMap.Keys && id != cacheID :: DecryptMap[id];
}
Expand Down
3 changes: 1 addition & 2 deletions src/SDK/CMM/DefaultCMM.dfy
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,7 @@ module {:extern "DefaultCMMDef"} DefaultCMMDef {
reads this, Repr
ensures Valid() ==> this in Repr
{
this in Repr &&
keyring in Repr && keyring.Repr <= Repr && this !in keyring.Repr && keyring.Valid()
this in Repr && ValidComponent(keyring)
}

constructor OfKeyring(k: KeyringDefs.Keyring)
Expand Down
10 changes: 3 additions & 7 deletions src/SDK/CMM/Defs.dfy
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,13 @@ module {:extern "CMMDefs"} CMMDefs {
import Signature
import EncryptionContext

trait {:termination false} CMM {
ghost var Repr: set<object>
predicate Valid()
reads this, Repr
ensures Valid() ==> this in Repr
trait {:termination false} CMM extends Validatable {

method GetEncryptionMaterials(materialsRequest: Materials.EncryptionMaterialsRequest)
returns (res: Result<Materials.ValidEncryptionMaterials>)
requires Valid()
modifies Repr
ensures Valid() && fresh(Repr - old(Repr))
ensures ValidAndFresh()
ensures res.Success? ==> res.value.Serializable()

// The following predicate is a synonym for Encryption.Serializable and provides a workaround for a translation bug
Expand All @@ -38,7 +34,7 @@ module {:extern "CMMDefs"} CMMDefs {
returns (res: Result<Materials.ValidDecryptionMaterials>)
requires Valid()
modifies Repr
ensures Valid() && fresh(Repr - old(Repr))
ensures ValidAndFresh()
ensures res.Success? ==> res.value.plaintextDataKey.Some?
}
}
6 changes: 1 addition & 5 deletions src/SDK/Keyring/Defs.dfy
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,7 @@ module {:extern "KeyringDefs"} KeyringDefs {
import Materials
import AlgorithmSuite

trait {:termination false} Keyring {
ghost var Repr: set<object>
predicate Valid()
reads this, Repr
ensures Valid() ==> this in Repr
trait {:termination false} Keyring extends Validatable {

method OnEncrypt(materials: Materials.ValidEncryptionMaterials) returns (res: Result<Materials.ValidEncryptionMaterials>)
requires Valid()
Expand Down
2 changes: 1 addition & 1 deletion src/SDK/Keyring/KMSKeyring.dfy
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ module {:extern "KMSKeyringDef"} KMSKeyringDef {
&& this in Repr
&& 0 <= |grantTokens| <= KMSUtils.MAX_GRANT_TOKENS
&& (|keyIDs| == 0 && generator.None? ==> isDiscovery)
&& (clientSupplier in Repr && clientSupplier.Repr <= Repr && this !in clientSupplier.Repr && clientSupplier.Valid())
&& ValidComponent(clientSupplier)
}

constructor (clientSupplier: KMSUtils.DafnyAWSKMSClientSupplier, keyIDs: seq<KMSUtils.CustomerMasterKey>, generator: Option<KMSUtils.CustomerMasterKey>, grantTokens: seq<KMSUtils.GrantToken>)
Expand Down
4 changes: 2 additions & 2 deletions src/SDK/Keyring/MultiKeyring.dfy
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,8 @@ module {:extern "MultiKeyringDef"} MultiKeyringDef {
ensures Valid() ==> this in Repr
{
&& this in Repr
&& (generator != null ==> generator in Repr && generator.Repr <= Repr && generator.Valid())
&& (forall j :: 0 <= j < |children| ==> children[j] in Repr && children[j].Repr <= Repr && children[j].Valid())
&& (generator == null || ValidComponent(generator))
&& (forall j :: 0 <= j < |children| ==> ValidComponent(children[j]))
}

method OnEncrypt(materials: Materials.ValidEncryptionMaterials) returns (res: Result<Materials.ValidEncryptionMaterials>)
Expand Down
6 changes: 2 additions & 4 deletions src/SDK/Keyring/RawRSAKeyring.dfy
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,9 @@ module {:extern "RawRSAKeyringDef"} RawRSAKeyringDef {
{
this in Repr &&
(publicKey.Some? || privateKey.Some?) &&
(publicKey.Some? ==>
publicKey.get in Repr && publicKey.get.Repr <= Repr && this !in publicKey.get.Repr && publicKey.get.Valid()) &&
(publicKey.Some? ==> ValidComponent(publicKey.get)) &&
(publicKey.Some? ==> publicKey.get.padding == paddingMode) &&
(privateKey.Some? ==>
privateKey.get in Repr && privateKey.get.Repr <= Repr && this !in privateKey.get.Repr && privateKey.get.Valid()) &&
(privateKey.Some? ==> ValidComponent(privateKey.get)) &&
(privateKey.Some? ==> privateKey.get.padding == paddingMode) &&
|keyNamespace| < UINT16_LIMIT &&
|keyName| < UINT16_LIMIT
Expand Down
39 changes: 39 additions & 0 deletions src/StandardLibrary/StandardLibrary.dfy
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,45 @@ include "UInt.dfy"
module {:extern "STL"} StandardLibrary {
import opened U = UInt

// A trait for objects with a Valid() predicate. Necessary in order to
// generalize some proofs, but also useful for reducing the boilerplate
// that most such objects need to include.
trait {:termination false} Validatable {
// TODO-RS: The style guide actually implies this should be "repr",
// but the convention is well-established at this point.
Comment on lines +13 to +14
Copy link
Contributor

Choose a reason for hiding this comment

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

I think we should update the style guide. I suggest it be updated to say that "public" fields (or, at least, public ghost fields) be capitalized, where "public" means "intended to be used and understood by clients".

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Should that also align with the set of symbols you export then?

ghost var Repr: set<object>

predicate Valid()
reads this, Repr
ensures Valid() ==> this in Repr

// Convenience predicate for when your object's validity depends on one
// or more other objects.
predicate ValidComponent(component: Validatable)
Copy link
Contributor

Choose a reason for hiding this comment

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

Having convenience predicates like this is fantastic!

reads this, Repr
ensures ValidComponent(component) ==> (
&& component in Repr
&& component.Repr <= Repr
&& this !in component.Repr
&& component.Valid())
Comment on lines +25 to +29
Copy link
Contributor

Choose a reason for hiding this comment

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

This postcondition is not necessary, since it just restates the body and functions are transparent (non-opaque) in Dafny (unless you limit visibility with an export clause, but you're not).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I was convinced this was necessary for validation for some reason, perhaps it was confounded with whatever the real fix was. Will try removing.

{
&& component in Repr
&& component.Repr <= Repr
&& this !in component.Repr
&& component.Valid()
}

// Convenience predicate, since you often want to assert that
// new objects in Repr are fresh as well.
// TODO-RS: Better name?
twostate predicate ValidAndFresh()
reads this, Repr
ensures ValidAndFresh() ==> Valid() && fresh(Repr - old(Repr))
Comment on lines +39 to +42
Copy link
Contributor

Choose a reason for hiding this comment

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

Is there a benefit to writing ValidAndFresh() as opposed to Valid() && Fresh()? The former doesn't seem much more convenient, whereas the latter is easier to name (except perhaps for confusion between fresh() and Fresh()).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It's questionable whether this is worth the trouble. I definitely DON'T think just "Fresh" is the right word anyway, so I'd rather come up with better or just drop this predicate. I'm more just observing this is a very common pattern.

Copy link
Contributor

Choose a reason for hiding this comment

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

Ditto. This postcondition is not necessary.

{
Valid() && fresh(Repr - old(Repr))
}
}

// TODO: Depend on types defined in dafny-lang/libraries instead
datatype Option<+T> = None | Some(get: T)
{
Expand Down
18 changes: 6 additions & 12 deletions src/Util/Streams.dfy
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,7 @@ module Streams {
import opened StandardLibrary
import opened UInt = StandardLibrary.UInt

class SeqReader<T> {
ghost var Repr: set<object>
class SeqReader<T> extends Validatable {
const data: seq<T>
var pos: nat

Expand Down Expand Up @@ -66,16 +65,14 @@ module Streams {
}
}

class ByteReader {
ghost var Repr: set<object>
class ByteReader extends Validatable {
const reader: SeqReader<uint8>

predicate Valid()
reads this, Repr
ensures Valid() ==> this in Repr
{
this in Repr &&
reader in Repr && reader.Repr <= Repr && this !in reader.Repr && reader.Valid()
this in Repr && ValidComponent(reader)
}

constructor (s: seq<uint8>)
Expand Down Expand Up @@ -188,8 +185,7 @@ module Streams {
}
}

class SeqWriter<T> {
ghost var Repr: set<object>
class SeqWriter<T> extends Validatable {
var data: seq<T>

predicate Valid()
Expand Down Expand Up @@ -221,16 +217,14 @@ module Streams {
}
}

class ByteWriter {
ghost var Repr: set<object>
class ByteWriter extends Validatable {
const writer: SeqWriter<uint8>

predicate Valid()
reads this, Repr
ensures Valid() ==> this in Repr
{
this in Repr &&
writer in Repr && writer.Repr <= Repr && this !in writer.Repr && writer.Valid()
this in Repr && ValidComponent(writer)
}

constructor()
Expand Down
4 changes: 2 additions & 2 deletions test/SDK/CMM/CachingCMM.dfy
Original file line number Diff line number Diff line change
Expand Up @@ -243,7 +243,7 @@ module TestCachingCMM {
returns (res: Result<Materials.ValidEncryptionMaterials>)
requires Valid()
modifies Repr
ensures Valid() && fresh(Repr - old(Repr))
ensures ValidAndFresh()
ensures res.Success? ==> res.value.plaintextDataKey.Some? && res.value.Serializable()
{
TestUtils.ExpectSerializableEncryptionContext(materialsRequest.encryptionContext);
Expand Down Expand Up @@ -279,7 +279,7 @@ module TestCachingCMM {
returns (res: Result<Materials.ValidDecryptionMaterials>)
requires Valid()
modifies Repr
ensures Valid() && fresh(Repr - old(Repr))
ensures ValidAndFresh()
ensures res.Success? ==> res.value.plaintextDataKey.Some?
{
var dm := Materials.DecryptionMaterials(
Expand Down