async _onEncrypt()

in modules/kms-keyring/src/kms_mrk_keyring.ts [119:254]


    async _onEncrypt(
      material: EncryptionMaterial<S>
    ): Promise<EncryptionMaterial<S>> {
      const { client, keyId, grantTokens } = this
      //= compliance/framework/aws-kms/aws-kms-mrk-aware-symmetric-keyring.txt#2.7
      //# If the input encryption materials (structures.md#encryption-
      //# materials) do not contain a plaintext data key OnEncrypt MUST attempt
      //# to generate a new plaintext data key by calling AWS KMS
      //# GenerateDataKey (https://docs.aws.amazon.com/kms/latest/APIReference/
      //# API_GenerateDataKey.html).
      if (!material.hasUnencryptedDataKey) {
        //= compliance/framework/aws-kms/aws-kms-mrk-aware-symmetric-keyring.txt#2.7
        //# The keyring MUST call
        //# AWS KMS GenerateDataKeys with a request constructed as follows:
        //
        //= compliance/framework/aws-kms/aws-kms-mrk-aware-symmetric-keyring.txt#2.7
        //# If the call to AWS KMS GenerateDataKey
        //# (https://docs.aws.amazon.com/kms/latest/APIReference/
        //# API_GenerateDataKey.html) does not succeed, OnEncrypt MUST NOT modify
        //# the encryption materials (structures.md#encryption-materials) and
        //# MUST fail.
        const dataKey = await generateDataKey(
          //= compliance/framework/aws-kms/aws-kms-mrk-aware-symmetric-keyring.txt#2.7
          //# If the keyring calls AWS KMS GenerateDataKeys, it MUST use the
          //# configured AWS KMS client to make the call.
          client,
          material.suite.keyLengthBytes,
          keyId,
          material.encryptionContext,
          grantTokens
        )
        /* This should be impossible given that generateDataKey only returns false if the client supplier does. */
        needs(dataKey, 'Generator KMS key did not generate a data key')

        //= compliance/framework/aws-kms/aws-kms-mrk-aware-symmetric-keyring.txt#2.7
        //# The Generate Data Key response's "KeyId" MUST be A valid AWS
        //# KMS key ARN (aws-kms-key-arn.md#identifying-an-aws-kms-multi-region-
        //# key).
        needs(parseAwsKmsKeyArn(dataKey.KeyId), 'Malformed arn.')

        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,
        }

        //= compliance/framework/aws-kms/aws-kms-mrk-aware-symmetric-keyring.txt#2.7
        //# If verified,
        //# OnEncrypt MUST do the following with the response from AWS KMS
        //# GenerateDataKey (https://docs.aws.amazon.com/kms/latest/APIReference/
        //# API_GenerateDataKey.html):
        material
          //= compliance/framework/aws-kms/aws-kms-mrk-aware-symmetric-keyring.txt#2.7
          //# If the Generate Data Key call succeeds, OnEncrypt MUST verify that
          //# the response "Plaintext" length matches the specification of the
          //# algorithm suite (algorithm-suites.md)'s Key Derivation Input Length
          //# field.
          //
          // setUnencryptedDataKey will throw if the plaintext does not match the algorithm suite requirements.
          .setUnencryptedDataKey(dataKey.Plaintext, trace)
          .addEncryptedDataKey(
            kmsResponseToEncryptedDataKey(dataKey),
            KeyringTraceFlag.WRAPPING_KEY_ENCRYPTED_DATA_KEY |
              KeyringTraceFlag.WRAPPING_KEY_SIGNED_ENC_CTX
          )

        //= compliance/framework/aws-kms/aws-kms-mrk-aware-symmetric-keyring.txt#2.7
        //# *  OnEncrypt MUST output the modified encryption materials
        //# (structures.md#encryption-materials)
        return material
      } else {
        //= compliance/framework/aws-kms/aws-kms-mrk-aware-symmetric-keyring.txt#2.7
        //# Given a plaintext data key in the encryption materials
        //# (structures.md#encryption-materials), OnEncrypt MUST attempt to
        //# encrypt the plaintext data key using the configured AWS KMS key
        //# identifier.

        const unencryptedDataKey = unwrapDataKey(
          material.getUnencryptedDataKey()
        )

        const flags =
          KeyringTraceFlag.WRAPPING_KEY_ENCRYPTED_DATA_KEY |
          KeyringTraceFlag.WRAPPING_KEY_SIGNED_ENC_CTX

        //= compliance/framework/aws-kms/aws-kms-mrk-aware-symmetric-keyring.txt#2.7
        //# If the call to AWS KMS Encrypt
        //# (https://docs.aws.amazon.com/kms/latest/APIReference/
        //# API_Encrypt.html) does not succeed, OnEncrypt MUST fail.
        //
        //= compliance/framework/aws-kms/aws-kms-mrk-aware-symmetric-keyring.txt#2.7
        //# The keyring
        //# MUST AWS KMS Encrypt call with a request constructed as follows:
        const kmsEDK = await encrypt(
          //= compliance/framework/aws-kms/aws-kms-mrk-aware-symmetric-keyring.txt#2.7
          //# The keyring MUST call AWS KMS Encrypt
          //# (https://docs.aws.amazon.com/kms/latest/APIReference/
          //# API_Encrypt.html) using the configured AWS KMS client.
          client,
          unencryptedDataKey,
          keyId,
          material.encryptionContext,
          grantTokens
        )

        /* This should be impossible given that encrypt only returns false if the client supplier does. */
        needs(
          kmsEDK,
          'AwsKmsMrkAwareSymmetricKeyring failed to encrypt data key'
        )

        //= compliance/framework/aws-kms/aws-kms-mrk-aware-symmetric-keyring.txt#2.7
        //# If the Encrypt call succeeds The response's "KeyId" MUST be A valid
        //# AWS KMS key ARN (aws-kms-key-arn.md#identifying-an-aws-kms-multi-
        //# region-key).
        needs(parseAwsKmsKeyArn(kmsEDK.KeyId), 'Malformed arn.')

        //= compliance/framework/aws-kms/aws-kms-mrk-aware-symmetric-keyring.txt#2.7
        //# If verified, OnEncrypt MUST do the following with the response from
        //# AWS KMS Encrypt (https://docs.aws.amazon.com/kms/latest/APIReference/
        //# API_Encrypt.html):
        material.addEncryptedDataKey(
          kmsResponseToEncryptedDataKey(kmsEDK),
          flags
        )

        //= compliance/framework/aws-kms/aws-kms-mrk-aware-symmetric-keyring.txt#2.7
        //# If all Encrypt calls succeed, OnEncrypt MUST output the modified
        //# encryption materials (structures.md#encryption-materials).
        return material
      }
    }