in modules/kms-keyring/src/kms_mrk_keyring.ts [260:367]
async _onDecrypt(
material: DecryptionMaterial<S>,
encryptedDataKeys: EncryptedDataKey[]
): Promise<DecryptionMaterial<S>> {
//= compliance/framework/aws-kms/aws-kms-mrk-aware-symmetric-keyring.txt#2.8
//# If the decryption materials (structures.md#decryption-materials)
//# already contained a valid plaintext data key OnDecrypt MUST
//# immediately return the unmodified decryption materials
//# (structures.md#decryption-materials).
if (material.hasValidKey()) return material
const { client, keyId, grantTokens } = this
//= compliance/framework/aws-kms/aws-kms-mrk-aware-symmetric-keyring.txt#2.8
//# The set of encrypted data keys MUST first be filtered to match this
//# keyring's configuration.
const decryptableEDKs = encryptedDataKeys.filter(filterEDKs(keyId))
const cmkErrors: Catchable[] = []
//= compliance/framework/aws-kms/aws-kms-mrk-aware-symmetric-keyring.txt#2.8
//# For each encrypted data key in the filtered set, one at a time, the
//# OnDecrypt MUST attempt to decrypt the data key.
for (const edk of decryptableEDKs) {
const { providerId, encryptedDataKey } = edk
try {
//= compliance/framework/aws-kms/aws-kms-mrk-aware-symmetric-keyring.txt#2.8
//# When calling AWS KMS Decrypt
//# (https://docs.aws.amazon.com/kms/latest/APIReference/
//# API_Decrypt.html), the keyring MUST call with a request constructed
//# as follows:
const dataKey = await decrypt(
//= compliance/framework/aws-kms/aws-kms-mrk-aware-symmetric-keyring.txt#2.8
//# To attempt to decrypt a particular encrypted data key
//# (structures.md#encrypted-data-key), OnDecrypt MUST call AWS KMS
//# Decrypt (https://docs.aws.amazon.com/kms/latest/APIReference/
//# API_Decrypt.html) with the configured AWS KMS client.
client,
// For MRKs the key identifier MUST be the configured key identifer.
{ providerId, encryptedDataKey, providerInfo: this.keyId },
material.encryptionContext,
grantTokens
)
/* This should be impossible given that decrypt only returns false if the client supplier does
* or if the providerId is not "aws-kms", which we have already filtered out
*/
needs(dataKey, 'decrypt did not return a data key.')
//= compliance/framework/aws-kms/aws-kms-mrk-aware-symmetric-keyring.txt#2.8
//# * The "KeyId" field in the response MUST equal the configured AWS
//# KMS key identifier.
needs(
dataKey.KeyId === this.keyId,
'KMS Decryption key does not match the requested key id.'
)
const flags =
KeyringTraceFlag.WRAPPING_KEY_DECRYPTED_DATA_KEY |
KeyringTraceFlag.WRAPPING_KEY_VERIFIED_ENC_CTX
const trace: KeyringTrace = {
keyNamespace: KMS_PROVIDER_ID,
keyName: dataKey.KeyId,
flags,
}
//= compliance/framework/aws-kms/aws-kms-mrk-aware-symmetric-keyring.txt#2.8
//# If the response does satisfies these requirements then OnDecrypt MUST
//# do the following with the response:
//
//= compliance/framework/aws-kms/aws-kms-mrk-aware-symmetric-keyring.txt#2.8
//# * The length of the response's "Plaintext" MUST equal the key
//# derivation input length (algorithm-suites.md#key-derivation-input-
//# length) specified by the algorithm suite (algorithm-suites.md)
//# included in the input decryption materials
//# (structures.md#decryption-materials).
//
// setUnencryptedDataKey will throw if the plaintext does not match the algorithm suite requirements.
material.setUnencryptedDataKey(dataKey.Plaintext, trace)
return material
} catch (e) {
//= compliance/framework/aws-kms/aws-kms-mrk-aware-symmetric-keyring.txt#2.8
//# If this attempt
//# results in an error, then these errors MUST be collected.
//
//= compliance/framework/aws-kms/aws-kms-mrk-aware-symmetric-keyring.txt#2.8
//# If the response does not satisfies these requirements then an error
//# MUST be collected and the next encrypted data key in the filtered set
//# MUST be attempted.
cmkErrors.push({ errPlus: e })
}
}
//= compliance/framework/aws-kms/aws-kms-mrk-aware-symmetric-keyring.txt#2.8
//# If OnDecrypt fails to successfully decrypt any encrypted data key
//# (structures.md#encrypted-data-key), then it MUST yield an error that
//# includes all the collected errors.
needs(
material.hasValidKey(),
[
`Unable to decrypt data key${
!decryptableEDKs.length ? ': No EDKs supplied' : ''
}.`,
...cmkErrors.map((e, i) => `Error #${i + 1} \n${e.errPlus.stack}`),
].join('\n')
)
return material
}