static createCipherBundle(serverSideEncryptionInfo,
                              log, cb, opts) {
        const { algorithm, configuredMasterKeyId, masterKeyId: bucketMasterKeyId } = serverSideEncryptionInfo;

        let masterKeyId = bucketMasterKeyId;
        if (configuredMasterKeyId) {
            log.debug('using user configured kms master key id');
            masterKeyId = configuredMasterKeyId;
        }
        // shadowing global client for key
        // but should not happen to cipher for another client as Puts should use current KMS
        // still extract KeyId and validate arn
        const { error, client, implName, clientIdentifier, key } = getClientForKey(masterKeyId, log);
        if (error) {
            return cb(error);
        }
        if (previousIdentifier
            && clientIdentifier === previousIdentifier
            && clientIdentifier !== currentIdentifier
            && (opts && !opts.previousOk)
        ) {
            return cb(errors.InvalidArgument
                .customizeDescription(
                    'KMS cannot use previous provider to encrypt new objects if a new provider is configured'));
        }

        const cipherBundle = {
            algorithm,
            masterKeyId, // keep arnPrefix in cipherBundle as it is returned to callback
            cryptoScheme: 1,
            cipheredDataKey: null,
            cipher: null,
        };

        return async.waterfall([
            function generateDataKey(next) {
                /* There are 2 ways of generating a datakey :
                  - using the generateDataKey of the KMS backend if it exists
                    (currently only implemented for the AWS KMS backend). This is
                    the preferred solution since a dedicated KMS should offer a better
                    entropy for generating random content.
                  - using local random number generation, and then use the KMS to
                    encrypt the datakey. This method is used when the KMS backend doesn't
                    provide the generateDataKey method.
                */
                let res;
                if (client.generateDataKey) {
                    log.debug('creating a data key using the KMS');
                    res = client.generateDataKey(cipherBundle.cryptoScheme,
                        key,
                        log, (err, plainTextDataKey, cipheredDataKey) => {
                            if (err) {
                                log.debug('error generating a new data key from KMS',
                                    { implName, error: err });
                                return next(err);
                            }
                            log.trace('data key generated by the kms');
                            return next(null, plainTextDataKey, cipheredDataKey);
                        });
                } else {
                    log.debug('creating a new data key');
                    const plainTextDataKey = Common.createDataKey();

                    log.debug('ciphering the data key');
                    res = client.cipherDataKey(cipherBundle.cryptoScheme,
                        key,
                        plainTextDataKey, log, (err, cipheredDataKey) => {
                            if (err) {
                                log.debug('error encrypting the data key using KMS',
                                    { implName, error: err });
                                return next(err);
                            }
                            log.trace('data key ciphered by the kms');
                            return next(null, plainTextDataKey, cipheredDataKey);
                        });
                }
                return res;
            },
            function createCipher(plainTextDataKey, cipheredDataKey, next) {
                log.debug('creating a cipher');
                cipherBundle.cipheredDataKey =
                    cipheredDataKey.toString('base64');
                return Common.createCipher(cipherBundle.cryptoScheme,
                    plainTextDataKey, 0, log, (err, cipher) => {
                        plainTextDataKey.fill(0);
                        if (err) {
                            log.debug('error from kms',
                            { implName, error: err });
                            return next(err);
                        }
                        log.trace('cipher created by the kms');
                        return next(null, cipher);
                    });
            },
            function finishCipherBundle(cipher, next) {
                cipherBundle.cipher = cipher;
                return next(null, cipherBundle);
            },
        ], (err, cipherBundle) => {
            if (err) {
                log.error('error processing cipher bundle',
                          { implName, error: err });
            }
            return cb(err, cipherBundle);
        });
    }
createCipherBundle
@param {object} serverSideEncryptionInfo - info for encryption
@param {number} serverSideEncryptionInfo.cryptoScheme -
cryptoScheme used
@param {string} serverSideEncryptionInfo.algorithm -
algorithm to use
@param {string} serverSideEncryptionInfo.masterKeyId -
key to get master key
@param {boolean} serverSideEncryptionInfo.mandatory -
true for mandatory encryption
@param {object} log - logger object
@param {function} cb - cb from external call
@param {object} [opts] - additional options
@param {boolean} [opts.previousOk] - allow usage of previous KMS (for ongoing MPU not migrated)
@returns {undefined}
@callback called with (err, cipherBundle)