Skip to content

Commit

Permalink
feat(HierarchyKeyring; CMC): Shared cache across Hierarchy Keyrings (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
RitvikKapila authored Sep 23, 2024
1 parent 36ede26 commit d4709e9
Show file tree
Hide file tree
Showing 17 changed files with 993 additions and 96 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -719,6 +719,7 @@ module {:extern "software.amazon.cryptography.materialproviders.internaldafny.ty
| SingleThreaded(SingleThreaded: SingleThreadedCache)
| MultiThreaded(MultiThreaded: MultiThreadedCache)
| StormTracking(StormTracking: StormTrackingCache)
| Shared(Shared: ICryptographicMaterialsCache)
class IClientSupplierCallHistory {
ghost constructor() {
GetClient := [];
Expand Down Expand Up @@ -823,7 +824,8 @@ module {:extern "software.amazon.cryptography.materialproviders.internaldafny.ty
nameonly branchKeyIdSupplier: Option<IBranchKeyIdSupplier> := Option.None ,
nameonly keyStore: AwsCryptographyKeyStoreTypes.IKeyStoreClient ,
nameonly ttlSeconds: PositiveLong ,
nameonly cache: Option<CacheType> := Option.None
nameonly cache: Option<CacheType> := Option.None ,
nameonly partitionId: Option<string> := Option.None
)
datatype CreateAwsKmsKeyringInput = | CreateAwsKmsKeyringInput (
nameonly kmsKeyId: KmsKeyId ,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,9 @@ union CacheType {
No: NoCache,
SingleThreaded: SingleThreadedCache,
MultiThreaded: MultiThreadedCache,
StormTracking: StormTrackingCache
StormTracking: StormTrackingCache,
@documentation("Shared cache across multiple Hierarchical Keyrings. For this cache type, the user should provide an already constructed CryptographicMaterialsCache to the Hierarchical Keyring at initialization.")
Shared: CryptographicMaterialsCacheReference
}

structure CreateCryptographicMaterialsCacheInput {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -339,8 +339,11 @@ structure CreateAwsKmsHierarchicalKeyringInput {
@javadoc("How many seconds the Branch Key material is allowed to be reused within the local cache before it is re-retrieved from Amazon DynamoDB and re-authenticated with AWS KMS.")
ttlSeconds: PositiveLong,

@javadoc("Which type of local cache to use.")
@documentation("Sets the type of cache for this Hierarchical Keyring. By providing an already initialized 'Shared' cache, users can determine the scope of the cache. That is, if the cache is shared across other Cryptographic Material Providers, for instance other Hierarchical Keyrings or Caching Cryptographic Materials Managers (Caching CMMs). If any other type of cache in the CacheType union is provided, the Hierarchical Keyring will initialize a cache of that type, to be used with only this Hierarchical Keyring. If not set, a DefaultCache is initialized to be used with only this Hierarchical Keyring with entryCapacity = 1000.")
cache : CacheType

@documentation("Partition ID to distinguish Cryptographic Material Providers (i.e: Keyrings) writing to a cache. If the Partition ID is the same for two Hierarchical Keyrings (or another Material Provider), they can share the same cache entries in the cache.")
partitionId : String
}

// Raw
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ module AwsCryptographyMaterialProvidersOperations refines AbstractAwsCryptograph
import Kms = Com.Amazonaws.Kms
import Ddb = ComAmazonawsDynamodbTypes
import RequiredEncryptionContextCMM
import UUID

datatype Config = Config(
nameonly crypto: Primitives.AtomicPrimitivesClient
Expand Down Expand Up @@ -260,16 +261,76 @@ module AwsCryptographyMaterialProvidersOperations refines AbstractAwsCryptograph
method CreateAwsKmsHierarchicalKeyring (config: InternalConfig, input: CreateAwsKmsHierarchicalKeyringInput)
returns (output: Result<IKeyring, Error>)
{
var maxCacheSize : int32;
// //= aws-encryption-sdk-specification/framework/aws-kms/aws-kms-hierarchical-keyring.md#initialization
// //= type=implication
//# If the Hierarchical Keyring does NOT get a `Shared` cache on initialization,
//# it MUST initialize a [cryptographic-materials-cache](../local-cryptographic-materials-cache.md)
//# with the user provided cache limit TTL and the entry capacity.
//# If no `cache` is provided, a `DefaultCache` MUST be configured with entry capacity of 1000.
var cmc;

if input.cache.Some? {
match input.cache.value {
case Shared(c) =>
cmc := c;
case _ =>
cmc :- CreateCryptographicMaterialsCache(
config,
CreateCryptographicMaterialsCacheInput(cache := input.cache.value)
);
}
}
else {
cmc :- CreateCryptographicMaterialsCache(
config,
CreateCryptographicMaterialsCacheInput(
cache := Types.Default(
Types.DefaultCache(entryCapacity := 1000)
)
)
);
}

//= aws-encryption-sdk-specification/framework/aws-kms/aws-kms-hierarchical-keyring.md#initialization
//= type=implication
//# If no max cache size is provided, the crypotgraphic materials cache MUST be configured to a
//# max cache size of 1000.
var cache := if input.cache.Some? then
input.cache.value
else
Types.Default(Types.DefaultCache(entryCapacity := 1000));
// //= aws-encryption-sdk-specification/framework/aws-kms/aws-kms-hierarchical-keyring.md#partition-id
// //= type=implication
//# PartitionId can be a string provided by the user. If provided, it MUST be interpreted as UTF8 bytes.
//# If the PartitionId is NOT provided by the user, it MUST be set to the 16 byte representation of a v4 UUID.
var partitionIdBytes : seq<uint8>;

if input.partitionId.Some? {
partitionIdBytes :- UTF8.Encode(input.partitionId.value)
.MapFailure(
e => Types.AwsCryptographicMaterialProvidersException(
message := "Could not UTF-8 Encode Partition ID: " + e
)
);
} else {
var uuid? := UUID.GenerateUUID();

var uuid :- uuid?
.MapFailure(e => Types.AwsCryptographicMaterialProvidersException(message := e));

partitionIdBytes :- UUID.ToByteArray(uuid)
.MapFailure(e => Types.AwsCryptographicMaterialProvidersException(message := e));
}

// //= aws-encryption-sdk-specification/framework/aws-kms/aws-kms-hierarchical-keyring.md#logical-key-store-name
// //= type=implication
//# Logical Key Store Name is set by the user when configuring the Key Store for
//# the Hierarchical Keyring. This is a logical name for the key store.
//# Logical Key Store Name MUST be converted to UTF8 Bytes to be used in
//# the cache identifiers.
var getKeyStoreInfoOutput? := input.keyStore.GetKeyStoreInfo();
var getKeyStoreInfoOutput :- getKeyStoreInfoOutput?
.MapFailure(e => Types.AwsCryptographyKeyStore(AwsCryptographyKeyStore := e));
var logicalKeyStoreName := getKeyStoreInfoOutput.logicalKeyStoreName;

var logicalKeyStoreNameBytes : seq<uint8> :- UTF8.Encode(logicalKeyStoreName)
.MapFailure(
e => Types.AwsCryptographicMaterialProvidersException(
message := "Could not UTF-8 Encode Logical Key Store Name: " + e
)
);

:- Need(input.branchKeyId.None? || input.branchKeyIdSupplier.None?,
Types.AwsCryptographicMaterialProvidersException(
Expand All @@ -279,14 +340,14 @@ module AwsCryptographyMaterialProvidersOperations refines AbstractAwsCryptograph
Types.AwsCryptographicMaterialProvidersException(
message := "Must initialize keyring with either branchKeyId or BranchKeyIdSupplier."));

var cmc :- CreateCryptographicMaterialsCache(config, CreateCryptographicMaterialsCacheInput(cache := cache));
var keyring := new AwsKmsHierarchicalKeyring.AwsKmsHierarchicalKeyring(
keyStore := input.keyStore,
branchKeyId := input.branchKeyId,
branchKeyIdSupplier := input.branchKeyIdSupplier,
ttlSeconds := input.ttlSeconds,
// maxCacheSize := maxCacheSize,
cmc := cmc,
partitionIdBytes := partitionIdBytes,
logicalKeyStoreNameBytes := logicalKeyStoreNameBytes,
cryptoPrimitives := config.crypto
);
return Success(keyring);
Expand Down Expand Up @@ -735,6 +796,10 @@ module AwsCryptographyMaterialProvidersOperations refines AbstractAwsCryptograph
);
var synCmc := new StormTrackingCMC.StormTrackingCMC(cmc);
return Success(synCmc);
case Shared(c) =>
var exception := Types.AwsCryptographicMaterialProvidersException(
message := "CreateCryptographicMaterialsCache should never be called with Shared CacheType.");
return Failure(exception);
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

include "../../Model/AwsCryptographyMaterialProvidersTypes.dfy"

module CacheConstants {
import opened StandardLibrary.UInt
import Seq

// Constants defined for cache identifier formulae

// Null Byte
const NULL_BYTE : seq<uint8> := [0x00]

// Resource Id
const RESOURCE_ID_CACHING_CMM: seq<uint8> := [0x01]
const RESOURCE_ID_HIERARCHICAL_KEYRING: seq<uint8> := [0x02]

// Scope Id
const SCOPE_ID_ENCRYPT: seq<uint8> := [0x01]
const SCOPE_ID_DECRYPT: seq<uint8> := [0x02]
const SCOPE_ID_SEARCHABLE_ENCRYPTION: seq<uint8> := [0x03]
}
Loading

0 comments on commit d4709e9

Please sign in to comment.