Skip to content

Commit 174b3bd

Browse files
committed
More citations
1 parent 0b4d46c commit 174b3bd

File tree

3 files changed

+282
-84
lines changed

3 files changed

+282
-84
lines changed

modules/kms-keyring-node/src/kms_hkeyring_node.ts

Lines changed: 110 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -51,12 +51,27 @@ import {
5151
import { randomBytes } from 'crypto'
5252

5353
export interface KmsHierarchicalKeyRingNodeInput {
54+
//= aws-encryption-sdk-specification/framework/aws-kms/aws-kms-hierarchical-keyring.md#initialization
55+
//= type=implication
56+
//# - MUST provide either a Branch Key Identifier or a [Branch Key Supplier](#branch-key-supplier)
5457
branchKeyId?: string
5558
branchKeyIdSupplier?: BranchKeyIdSupplier
59+
//= aws-encryption-sdk-specification/framework/aws-kms/aws-kms-hierarchical-keyring.md#initialization
60+
//= type=implication
61+
//# - MUST provide a [Keystore](../branch-key-store.md)
5662
keyStore: BranchKeyStoreNode
63+
//= aws-encryption-sdk-specification/framework/aws-kms/aws-kms-hierarchical-keyring.md#initialization
64+
//= type=implication
65+
//# - MUST provide a [cache limit TTL](#cache-limit-ttl)
5766
cacheLimitTtl: number
67+
//= aws-encryption-sdk-specification/framework/aws-kms/aws-kms-hierarchical-keyring.md#initialization
68+
//= type=exception
69+
//# - MAY provide a [Cache Type](#cache-type)
5870
cache?: CryptographicMaterialsCache<NodeAlgorithmSuite>
5971
maxCacheSize?: number
72+
//= aws-encryption-sdk-specification/framework/aws-kms/aws-kms-hierarchical-keyring.md#initialization
73+
//= type=implication
74+
//# - MAY provide a [Partition ID](#partition-id)
6075
partitionId?: string
6176
}
6277

@@ -74,6 +89,9 @@ export interface IKmsHierarchicalKeyRingNode extends KeyringNode {
7489

7590
export class KmsHierarchicalKeyRingNode
7691
extends KeyringNode
92+
//= aws-encryption-sdk-specification/framework/aws-kms/aws-kms-hierarchical-keyring.md#interface
93+
//= type=implication
94+
//# MUST implement the [AWS Encryption SDK Keyring interface](../keyring-interface.md#interface)
7795
implements IKmsHierarchicalKeyRingNode
7896
{
7997
public declare branchKeyId?: string
@@ -96,8 +114,33 @@ export class KmsHierarchicalKeyRingNode
96114
}: KmsHierarchicalKeyRingNodeInput) {
97115
super()
98116

99-
needs(!partitionId || typeof partitionId === 'string', 'Partition id must be a string.')
100-
readOnlyProperty(this, '_partition', partitionId ? stringToUtf8Bytes(partitionId) : randomBytes(64))
117+
needs(
118+
!partitionId || typeof partitionId === 'string',
119+
'Partition id must be a string.'
120+
)
121+
122+
//= aws-encryption-sdk-specification/framework/aws-kms/aws-kms-hierarchical-keyring.md#partition-id
123+
//= type=implication
124+
//# The Partition ID MUST NOT be changed after initialization.
125+
readOnlyProperty(
126+
this,
127+
'_partition',
128+
129+
//= aws-encryption-sdk-specification/framework/aws-kms/aws-kms-hierarchical-keyring.md#partition-id-1
130+
//# It can either be a String provided by the user, which MUST be interpreted as the bytes of
131+
//# UTF-8 Encoding of the String, or a v4 UUID, which SHOULD be interpreted as the 16 byte representation of the UUID.
132+
133+
//= aws-encryption-sdk-specification/framework/aws-kms/aws-kms-hierarchical-keyring.md#partition-id-1
134+
//# The constructor of the Hierarchical Keyring MUST record these bytes at construction time.
135+
136+
//= aws-encryption-sdk-specification/framework/aws-kms/aws-kms-hierarchical-keyring.md#partition-id
137+
//# If provided, it MUST be interpreted as UTF8 bytes.
138+
139+
//= aws-encryption-sdk-specification/framework/aws-kms/aws-kms-hierarchical-keyring.md#partition-id
140+
//= type=exception
141+
//# If the PartitionId is NOT provided by the user, it MUST be set to the 16 byte representation of a v4 UUID.
142+
partitionId ? stringToUtf8Bytes(partitionId) : randomBytes(64)
143+
)
101144

102145
/* Precondition: The branch key id must be a string */
103146
if (branchKeyId) {
@@ -128,6 +171,9 @@ export class KmsHierarchicalKeyRingNode
128171
readOnlyProperty(
129172
this,
130173
'_logicalKeyStoreName',
174+
//= aws-encryption-sdk-specification/framework/aws-kms/aws-kms-hierarchical-keyring.md#logical-key-store-name
175+
//# Logical Key Store Name MUST be converted to UTF8 Bytes to be used in
176+
//# the cache identifiers.
131177
stringToUtf8Bytes(keyStore.getKeyStoreInfo().logicalKeyStoreName)
132178
)
133179

@@ -179,9 +225,6 @@ export class KmsHierarchicalKeyRingNode
179225
if (cache) {
180226
needs(!maxCacheSize, 'Max cache size not supported when passing a cache.')
181227
} else {
182-
183-
console.log(maxCacheSize)
184-
185228
/* Precondition: The max cache size must be a number */
186229
needs(
187230
// Order is important, 0 is a number but also false.
@@ -199,6 +242,13 @@ export class KmsHierarchicalKeyRingNode
199242
'Max cache size must be non-negative and less than or equal Number.MAX_SAFE_INTEGER'
200243
)
201244

245+
//= aws-encryption-sdk-specification/framework/aws-kms/aws-kms-hierarchical-keyring.md#initialization
246+
//# On initialization the Hierarchical Keyring MUST initialize a [cryptographic-materials-cache](../local-cryptographic-materials-cache.md) with the configured cache limit TTL and the max cache size.
247+
248+
//= aws-encryption-sdk-specification/framework/aws-kms/aws-kms-hierarchical-keyring.md#initialization
249+
//# If the Hierarchical Keyring does NOT get a `Shared` cache on initialization,
250+
//# it MUST initialize a [cryptographic-materials-cache](../local-cryptographic-materials-cache.md)
251+
//# with the user provided cache limit TTL and the entry capacity.
202252
cache = getLocalCryptographicMaterialsCache(maxCacheSize)
203253
}
204254
readOnlyProperty(this, 'maxCacheSize', maxCacheSize)
@@ -209,41 +259,25 @@ export class KmsHierarchicalKeyRingNode
209259
}
210260

211261
async _onEncrypt(
262+
//= aws-encryption-sdk-specification/framework/aws-kms/aws-kms-hierarchical-keyring.md#onencrypt
263+
//= type=implication
264+
//# OnEncrypt MUST take [encryption materials](../structures.md#encryption-materials) as input.
212265
encryptionMaterial: NodeEncryptionMaterial
213266
): Promise<NodeEncryptionMaterial> {
214267
//= aws-encryption-sdk-specification/framework/aws-kms/aws-kms-hierarchical-keyring.md#onencrypt
215268
//# The `branchKeyId` used in this operation is either the configured branchKeyId, if supplied, or the result of the `branchKeySupplier`'s
216269
//# `getBranchKeyId` operation, using the encryption material's encryption context as input.
217270
const branchKeyId = getBranchKeyId(this, encryptionMaterial)
218271

219-
// compute the cache entry id for the active branch key material that we
220-
// want
272+
//= aws-encryption-sdk-specification/framework/aws-kms/aws-kms-hierarchical-keyring.md#onencrypt
273+
//# The hierarchical keyring MUST use the formulas specified in [Appendix A](#appendix-a-cache-entry-identifier-formulas)
274+
//# to compute the [cache entry identifier](../cryptographic-materials-cache.md#cache-identifier).
221275
const cacheEntryId = getCacheEntryId(
222276
this._logicalKeyStoreName,
223277
this._partition,
224278
branchKeyId
225279
)
226280

227-
//= aws-encryption-sdk-specification/framework/aws-kms/aws-kms-hierarchical-keyring.md#onencrypt
228-
//# If a cache entry is found and the entry's TTL has not expired, the hierarchical keyring MUST use those branch key materials for key wrapping.
229-
230-
//= aws-encryption-sdk-specification/framework/aws-kms/aws-kms-hierarchical-keyring.md#onencrypt
231-
//# If a cache entry is not found or the cache entry is expired, the hierarchical keyring MUST attempt to obtain the branch key materials
232-
//# by querying the backing branch keystore specified in the [retrieve OnEncrypt branch key materials](#query-branch-keystore-onencrypt) section.
233-
//# If the keyring is not able to retrieve [branch key materials](../structures.md#branch-key-materials)
234-
//# through the underlying cryptographic materials cache or
235-
//# it no longer has access to them through the backing keystore, OnEncrypt MUST fail.
236-
237-
//= aws-encryption-sdk-specification/framework/aws-kms/aws-kms-hierarchical-keyring.md#query-branch-keystore-onencrypt
238-
//# The branch keystore persists [branch keys](#definitions) that are reused to derive unique data keys for envelope encryption to
239-
//# reduce the number of calls to AWS KMS through the use of the
240-
//# [cryptographic materials cache](../cryptographic-materials-cache.md).
241-
//# OnEncrypt MUST call the Keystore's [GetActiveBranchKey](../branch-key-store.md#getactivebranchkey) operation with the following inputs:
242-
//# - the `branchKeyId` used in this operation
243-
//# If the Keystore's GetActiveBranchKey operation succeeds
244-
//# the keyring MUST put the returned branch key materials in the cache using the
245-
//# formula defined in [Appendix A](#appendix-a-cache-entry-identifier-formulas).
246-
//# Otherwise, OnEncrypt MUST fail.
247281
const branchKeyMaterials = await getBranchKeyMaterials(
248282
this,
249283
this._cmc,
@@ -254,7 +288,12 @@ export class KmsHierarchicalKeyRingNode
254288
// get a pdk (generate it if not already set)
255289
const pdk = getPlaintextDataKey(encryptionMaterial)
256290

257-
// encrypt the pdk
291+
//= aws-encryption-sdk-specification/framework/aws-kms/aws-kms-hierarchical-keyring.md#onencrypt
292+
//# If the keyring is unable to wrap a plaintext data key, OnEncrypt MUST fail
293+
//# and MUST NOT modify the [decryption materials](structures.md#decryption-materials).
294+
295+
//= aws-encryption-sdk-specification/framework/aws-kms/aws-kms-hierarchical-keyring.md#onencrypt
296+
//# - MUST wrap a data key with the branch key materials according to the [branch key wrapping](#branch-key-wrapping) section.
258297
const edk = wrapPlaintextDataKey(
259298
pdk,
260299
branchKeyMaterials,
@@ -267,6 +306,9 @@ export class KmsHierarchicalKeyRingNode
267306
}
268307

269308
async onDecrypt(
309+
//= aws-encryption-sdk-specification/framework/aws-kms/aws-kms-hierarchical-keyring.md#ondecrypt
310+
//= type=implication
311+
//# OnDecrypt MUST take [decryption materials](../structures.md#decryption-materials) and a list of [encrypted data keys](../structures.md#encrypted-data-keys) as input.
270312
material: NodeDecryptionMaterial,
271313
encryptedDataKeys: EncryptedDataKey[]
272314
): Promise<DecryptionMaterial<NodeAlgorithmSuite>> {
@@ -319,23 +361,30 @@ export class KmsHierarchicalKeyRingNode
319361
for (const { encryptedDataKey: ciphertext } of filteredEdkObjs) {
320362
let udk: Uint8Array | undefined = undefined
321363
try {
364+
//= aws-encryption-sdk-specification/framework/aws-kms/aws-kms-hierarchical-keyring.md#getitem-branch-keystore-ondecrypt
365+
//# - Deserialize the UUID string representation of the `version` from the [encrypted data key](../structures.md#encrypted-data-key) [ciphertext](#ciphertext).
322366
// get the branch key version (as compressed bytes) from the
323367
// destructured ciphertext of the edk
324368
const { branchKeyVersionAsBytesCompressed } = destructureCiphertext(
325369
ciphertext,
326370
decryptionMaterial.suite
327371
)
328372

373+
//= aws-encryption-sdk-specification/framework/aws-kms/aws-kms-hierarchical-keyring.md#getitem-branch-keystore-ondecrypt
374+
//# - The deserialized UUID string representation of the `version`
329375
// uncompress the branch key version into regular utf8 bytes
330376
const branchKeyVersionAsBytes = stringToUtf8Bytes(
331377
decompressBytesToUuidv4(branchKeyVersionAsBytesCompressed)
332378
)
333379

334-
// compute the cache entry id for the versioned branch key material that we
335-
// want
380+
//= aws-encryption-sdk-specification/framework/aws-kms/aws-kms-hierarchical-keyring.md#ondecrypt
381+
//# The hierarchical keyring MUST use the OnDecrypt formula specified in [Appendix A](#decryption-materials)
382+
//# in order to compute the [cache entry identifier](cryptographic-materials-cache.md#cache-identifier).
336383
const cacheEntryId = getCacheEntryId(
337384
this._logicalKeyStoreName,
338385
this._partition,
386+
//= aws-encryption-sdk-specification/framework/aws-kms/aws-kms-hierarchical-keyring.md#getitem-branch-keystore-ondecrypt
387+
//# OnDecrypt MUST calculate the following values:
339388
branchKeyId,
340389
branchKeyVersionAsBytes
341390
)
@@ -346,29 +395,9 @@ export class KmsHierarchicalKeyRingNode
346395
)
347396

348397
//= aws-encryption-sdk-specification/framework/aws-kms/aws-kms-hierarchical-keyring.md#ondecrypt
349-
//# If a cache entry is found and the entry's TTL has not expired, the hierarchical keyring MUST use those branch key materials for key unwrapping.
350-
351-
//= aws-encryption-sdk-specification/framework/aws-kms/aws-kms-hierarchical-keyring.md#ondecrypt
352-
//# If a cache entry is not found or the cache entry is expired, the hierarchical keyring
353-
//# MUST attempt to obtain the branch key materials by calling the backing branch key
354-
//# store specified in the [retrieve OnDecrypt branch key materials](#getitem-branch-keystore-ondecrypt) section.
355-
//# If the keyring is not able to retrieve `branch key materials` from the backing keystore then OnDecrypt MUST fail.
356-
357-
//= aws-encryption-sdk-specification/framework/aws-kms/aws-kms-hierarchical-keyring.md#getitem-branch-keystore-ondecrypt
358-
//# The branch keystore persists [branch keys](#definitions) that are reused to derive unique data keys for key wrapping to
359-
//# reduce the number of calls to AWS KMS through the use of the
360-
//# [cryptographic materials cache](../cryptographic-materials-cache.md).
361-
//# OnDecrypt MUST calculate the following values:
362-
//# - Deserialize the UTF8-Decoded `branch-key-id` from the [key provider info](../structures.md#key-provider-information) of the [encrypted data key](../structures.md#encrypted-data-key)
363-
//# and verify this is equal to the configured or supplied `branch-key-id`.
364-
//# - Deserialize the UUID string representation of the `version` from the [encrypted data key](../structures.md#encrypted-data-key) [ciphertext](#ciphertext).
365-
//# OnDecrypt MUST call the Keystore's [GetBranchKeyVersion](../branch-key-store.md#getbranchkeyversion) operation with the following inputs:
366-
//# - The deserialized, UTF8-Decoded `branch-key-id`
367-
//# - The deserialized UUID string representation of the `version`
368-
//# If the Keystore's GetBranchKeyVersion operation succeeds
369-
//# the keyring MUST put the returned branch key materials in the cache using the
370-
//# formula defined in [Appendix A](#appendix-a-cache-entry-identifier-formulas).
371-
//# Otherwise, OnDecrypt MUST fail.
398+
//# To decrypt each encrypted data key in the filtered set, the hierarchical keyring MUST attempt
399+
//# to find the corresponding [branch key materials](../structures.md#branch-key-materials)
400+
//# from the underlying [cryptographic materials cache](../local-cryptographic-materials-cache.md).
372401
const branchKeyMaterials = await getBranchKeyMaterials(
373402
this,
374403
this._cmc,
@@ -377,7 +406,8 @@ export class KmsHierarchicalKeyRingNode
377406
branchKeyVersionAsString
378407
)
379408

380-
// unwrap the edk to get the udk/pdk
409+
//= aws-encryption-sdk-specification/framework/aws-kms/aws-kms-hierarchical-keyring.md#ondecrypt
410+
//# - MUST unwrap the encrypted data key with the branch key materials according to the [branch key unwrapping](#branch-key-unwrapping) section.
381411
udk = unwrapEncryptedDataKey(
382412
ciphertext,
383413
branchKeyMaterials,
@@ -412,3 +442,29 @@ export class KmsHierarchicalKeyRingNode
412442
}
413443

414444
immutableClass(KmsHierarchicalKeyRingNode)
445+
446+
// The JS version has not been released with a Storm Tracking CMC
447+
448+
//= aws-encryption-sdk-specification/framework/aws-kms/aws-kms-hierarchical-keyring.md#initialization
449+
//= type=exception
450+
//# If the cache to initialize is a [Storm Tracking Cryptographic Materials Cache](../storm-tracking-cryptographic-materials-cache.md#overview)
451+
//# then the [Grace Period](../storm-tracking-cryptographic-materials-cache.md#grace-period) MUST be less than the [cache limit TTL](#cache-limit-ttl).
452+
453+
//= aws-encryption-sdk-specification/framework/aws-kms/aws-kms-hierarchical-keyring.md#initialization
454+
//= type=exception
455+
//# If no `cache` is provided, a `DefaultCache` MUST be configured with entry capacity of 1000.
456+
457+
// These are not something we can enforce
458+
459+
//= aws-encryption-sdk-specification/framework/aws-kms/aws-kms-hierarchical-keyring.md#logical-key-store-name
460+
//= type=exception
461+
//# > Note: Users MUST NEVER have two different physical Key Stores with the same Logical Key Store Name.
462+
463+
//= aws-encryption-sdk-specification/framework/aws-kms/aws-kms-hierarchical-keyring.md#shared-cache-considerations
464+
//= type=exception
465+
//# Any keyring that has access to the `Shared` cache MAY be able to use materials
466+
//# that it MAY or MAY NOT have direct access to.
467+
//#
468+
//# Users MUST make sure that all of Partition ID, Logical Key Store Name of the Key Store for the Hierarchical Keyring
469+
//# and Branch Key ID are set to be the same for two Hierarchical Keyrings if and only they want the keyrings to share
470+
//# cache entries.

0 commit comments

Comments
 (0)