in modules/kms-keyring/src/kms_keyring.ts [156:229]
async _onEncrypt(material: EncryptionMaterial<S>) {
/* Check for early return (Postcondition): Discovery Keyrings do not encrypt. */
if (this.isDiscovery) return material
const keyIds = this.keyIds.slice()
const { clientProvider, generatorKeyId, grantTokens } = this
if (generatorKeyId && !material.hasUnencryptedDataKey) {
const dataKey = await generateDataKey(
clientProvider,
material.suite.keyLengthBytes,
generatorKeyId,
material.encryptionContext,
grantTokens
)
/* Precondition: A generatorKeyId must generate if we do not have an unencrypted data key.
* Client supplier is allowed to return undefined if, for example, user wants to exclude particular
* regions. But if we are here it means that user configured keyring with a KMS key that was
* incompatible with the client supplier in use.
*/
if (!dataKey)
throw new Error('Generator KMS key did not generate a data key')
const flags =
KeyringTraceFlag.WRAPPING_KEY_GENERATED_DATA_KEY |
KeyringTraceFlag.WRAPPING_KEY_SIGNED_ENC_CTX |
KeyringTraceFlag.WRAPPING_KEY_ENCRYPTED_DATA_KEY
const trace: KeyringTrace = {
keyNamespace: KMS_PROVIDER_ID,
keyName: dataKey.KeyId,
flags,
}
material
/* Postcondition: The generated unencryptedDataKey length must match the algorithm specification.
* See cryptographic_materials as setUnencryptedDataKey will throw in this case.
*/
.setUnencryptedDataKey(dataKey.Plaintext, trace)
.addEncryptedDataKey(
kmsResponseToEncryptedDataKey(dataKey),
KeyringTraceFlag.WRAPPING_KEY_ENCRYPTED_DATA_KEY |
KeyringTraceFlag.WRAPPING_KEY_SIGNED_ENC_CTX
)
} else if (generatorKeyId) {
keyIds.unshift(generatorKeyId)
}
/* Precondition: If a generator does not exist, an unencryptedDataKey *must* already exist.
* Furthermore *only* CMK's explicitly designated as generators can generate data keys.
* See cryptographic_materials as getUnencryptedDataKey will throw in this case.
*/
const unencryptedDataKey = unwrapDataKey(material.getUnencryptedDataKey())
const flags =
KeyringTraceFlag.WRAPPING_KEY_ENCRYPTED_DATA_KEY |
KeyringTraceFlag.WRAPPING_KEY_SIGNED_ENC_CTX
for (const kmsKey of keyIds) {
const kmsEDK = await encrypt(
clientProvider,
unencryptedDataKey,
kmsKey,
material.encryptionContext,
grantTokens
)
/* clientProvider may not return a client, in this case there is not an EDK to add */
if (kmsEDK)
material.addEncryptedDataKey(
kmsResponseToEncryptedDataKey(kmsEDK),
flags
)
}
return material
}