// Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
import { getRegionFromIdentifier } from './arn_parsing';
import { EncryptedDataKey, needs, } from '@aws-crypto/material-management';
export const KMS_PROVIDER_ID = 'aws-kms';
export async function generateDataKey(clientProvider, NumberOfBytes, KeyId, EncryptionContext, GrantTokens) {
    const client = typeof clientProvider === 'function'
        ? clientProvider(getRegionFromIdentifier(KeyId))
        : clientProvider;
    /* Check for early return (Postcondition): clientProvider did not return a client for generateDataKey. */
    if (!client)
        return false;
    const v2vsV3Response = client.generateDataKey({
        KeyId,
        GrantTokens,
        NumberOfBytes,
        EncryptionContext,
    });
    const v2vsV3Promise = 'promise' in v2vsV3Response ? v2vsV3Response.promise() : v2vsV3Response;
    const dataKey = await v2vsV3Promise;
    return safeGenerateDataKey(dataKey);
}
export async function encrypt(clientProvider, Plaintext, KeyId, EncryptionContext, GrantTokens) {
    const client = typeof clientProvider === 'function'
        ? clientProvider(getRegionFromIdentifier(KeyId))
        : clientProvider;
    /* Check for early return (Postcondition): clientProvider did not return a client for encrypt. */
    if (!client)
        return false;
    const v2vsV3Response = client.encrypt({
        KeyId,
        Plaintext,
        EncryptionContext,
        GrantTokens,
    });
    const v2vsV3Promise = 'promise' in v2vsV3Response ? v2vsV3Response.promise() : v2vsV3Response;
    const kmsEDK = await v2vsV3Promise;
    return safeEncryptOutput(kmsEDK);
}
export async function decrypt(clientProvider, { providerId, providerInfo, encryptedDataKey }, EncryptionContext, GrantTokens) {
    /* Precondition:  The EDK must be a KMS edk. */
    needs(providerId === KMS_PROVIDER_ID, 'Unsupported providerId');
    const client = typeof clientProvider === 'function'
        ? clientProvider(getRegionFromIdentifier(providerInfo))
        : clientProvider;
    /* Check for early return (Postcondition): clientProvider did not return a client for decrypt. */
    if (!client)
        return false;
    /* The AWS KMS KeyId *must* be set. */
    const v2vsV3Response = client.decrypt({
        KeyId: providerInfo,
        CiphertextBlob: encryptedDataKey,
        EncryptionContext,
        GrantTokens,
    });
    const v2vsV3Promise = 'promise' in v2vsV3Response ? v2vsV3Response.promise() : v2vsV3Response;
    const dataKey = await v2vsV3Promise;
    return safeDecryptOutput(dataKey);
}
export function kmsResponseToEncryptedDataKey({ KeyId: providerInfo, CiphertextBlob: encryptedDataKey, }) {
    return new EncryptedDataKey({
        providerId: KMS_PROVIDER_ID,
        providerInfo,
        encryptedDataKey,
    });
}
function safeGenerateDataKey(dataKey) {
    /* Postcondition: KMS must return serializable generate data key. */
    needs(typeof dataKey.KeyId === 'string' &&
        dataKey.Plaintext instanceof Uint8Array &&
        dataKey.CiphertextBlob instanceof Uint8Array, 'Malformed KMS response.');
    return safePlaintext(dataKey);
}
function safeEncryptOutput(dataKey) {
    /* Postcondition: KMS must return serializable encrypted data key. */
    needs(typeof dataKey.KeyId === 'string' &&
        dataKey.CiphertextBlob instanceof Uint8Array, 'Malformed KMS response.');
    return dataKey;
}
function safeDecryptOutput(dataKey) {
    /* Postcondition: KMS must return usable decrypted key. */
    needs(typeof dataKey.KeyId === 'string' &&
        dataKey.Plaintext instanceof Uint8Array, 'Malformed KMS response.');
    return safePlaintext(dataKey);
}
function safePlaintext(dataKey) {
    /* The KMS Client *may* return a Buffer that is not isolated.
     * i.e. the byteOffset !== 0.
     * This means that the unencrypted data key is possibly accessible to someone else.
     * If this is the node shared Buffer, then other code within this process _could_ find this secret.
     * Copy Plaintext to an isolated ArrayBuffer and zero the Plaintext.
     * This means that this function will *always* zero out the value returned to it from the KMS client.
     * While this is safe to do here, copying this code somewhere else may produce unexpected results.
     */
    const { Plaintext } = dataKey;
    dataKey.Plaintext = new Uint8Array(Plaintext);
    Plaintext.fill(0);
    return dataKey;
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaGVscGVycy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9oZWxwZXJzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLG9FQUFvRTtBQUNwRSxzQ0FBc0M7QUFZdEMsT0FBTyxFQUFFLHVCQUF1QixFQUFFLE1BQU0sZUFBZSxDQUFBO0FBQ3ZELE9BQU8sRUFFTCxnQkFBZ0IsRUFDaEIsS0FBSyxHQUNOLE1BQU0saUNBQWlDLENBQUE7QUFFeEMsTUFBTSxDQUFDLE1BQU0sZUFBZSxHQUFHLFNBQVMsQ0FBQTtBQUV4QyxNQUFNLENBQUMsS0FBSyxVQUFVLGVBQWUsQ0FDbkMsY0FBa0QsRUFDbEQsYUFBcUIsRUFDckIsS0FBYSxFQUNiLGlCQUFvQyxFQUNwQyxXQUFzQjtJQUV0QixNQUFNLE1BQU0sR0FDVixPQUFPLGNBQWMsS0FBSyxVQUFVO1FBQ2xDLENBQUMsQ0FBQyxjQUFjLENBQUMsdUJBQXVCLENBQUMsS0FBSyxDQUFDLENBQUM7UUFDaEQsQ0FBQyxDQUFDLGNBQWMsQ0FBQTtJQUVwQix5R0FBeUc7SUFDekcsSUFBSSxDQUFDLE1BQU07UUFBRSxPQUFPLEtBQUssQ0FBQTtJQUN6QixNQUFNLGNBQWMsR0FBRyxNQUFNLENBQUMsZUFBZSxDQUFDO1FBQzVDLEtBQUs7UUFDTCxXQUFXO1FBQ1gsYUFBYTtRQUNiLGlCQUFpQjtLQUNsQixDQUFDLENBQUE7SUFDRixNQUFNLGFBQWEsR0FDakIsU0FBUyxJQUFJLGNBQWMsQ0FBQyxDQUFDLENBQUMsY0FBYyxDQUFDLE9BQU8sRUFBRSxDQUFDLENBQUMsQ0FBQyxjQUFjLENBQUE7SUFDekUsTUFBTSxPQUFPLEdBQUcsTUFBTSxhQUFhLENBQUE7SUFFbkMsT0FBTyxtQkFBbUIsQ0FBQyxPQUFPLENBQUMsQ0FBQTtBQUNyQyxDQUFDO0FBRUQsTUFBTSxDQUFDLEtBQUssVUFBVSxPQUFPLENBQzNCLGNBQWtELEVBQ2xELFNBQXFCLEVBQ3JCLEtBQWEsRUFDYixpQkFBb0MsRUFD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