// Licensed under the Apache License, Version 2.0 (the "License");
//
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
////////////////////////////////////////////////////////////////////////////////

goog.module('tink.subtle.EciesAeadHkdfHybridDecrypt');

const Aead = goog.require('tink.Aead');
const EciesAeadHkdfDemHelper = goog.require('tink.subtle.EciesAeadHkdfDemHelper');
const EciesHkdfKemRecipient = goog.require('tink.subtle.EciesHkdfKemRecipient');
const EllipticCurves = goog.require('tink.subtle.EllipticCurves');
const HybridDecrypt = goog.require('tink.HybridDecrypt');
const SecurityException = goog.require('tink.exception.SecurityException');

/**
 * Implementation of ECIES AEAD HKDF hybrid decryption.
 *
 * @implements {HybridDecrypt}
 * @protected
 * @final
 */
class EciesAeadHkdfHybridDecrypt {
  /**
   * @param {!webCrypto.JsonWebKey} recipientPrivateKey
   * @param {!EciesHkdfKemRecipient} kemRecipient
   * @param {string} hkdfHash the name of the HMAC algorithm, accepted names
   *     are: SHA-1, SHA-256 and SHA-512.
   * @param {!EllipticCurves.PointFormatType} pointFormat
   * @param {!EciesAeadHkdfDemHelper} demHelper
   * @param {!Uint8Array=} opt_hkdfSalt
   */
  constructor(
      recipientPrivateKey, kemRecipient, hkdfHash, pointFormat, demHelper,
      opt_hkdfSalt) {
    if (!recipientPrivateKey) {
      throw new SecurityException('Recipient private key has to be non-null.');
    }
    if (!kemRecipient) {
      throw new SecurityException('KEM recipient has to be non-null.');
    }
    if (!hkdfHash) {
      throw new SecurityException('HKDF hash algorithm has to be non-null.');
    }
    if (!pointFormat) {
      throw new SecurityException('Point format has to be non-null.');
    }
    if (!demHelper) {
      throw new SecurityException('DEM helper has to be non-null.');
    }

    const curveType =
        EllipticCurves.curveFromString(recipientPrivateKey['crv']);
    const headerSize =
        EllipticCurves.encodingSizeInBytes(curveType, pointFormat);

    /** @private @const {!EciesHkdfKemRecipient} */
    this.kemRecipient_ = kemRecipient;
    /** @private @const {string} */
    this.hkdfHash_ = hkdfHash;
    /** @private @const {!EllipticCurves.PointFormatType} */
    this.pointFormat_ = pointFormat;
    /** @private @const {!EciesAeadHkdfDemHelper} */
    this.demHelper_ = demHelper;
    /** @private @const {number} */
    this.headerSize_ = headerSize;
    /** @private @const {!Uint8Array|undefined} */
    this.hkdfSalt_ = opt_hkdfSalt;
  }

  /**
   * @param {!webCrypto.JsonWebKey} recipientPrivateKey
   * @param {string} hkdfHash the name of the HMAC algorithm, accepted names
   *     are: SHA-1, SHA-256 and SHA-512.
   * @param {!EllipticCurves.PointFormatType} pointFormat
   * @param {!EciesAeadHkdfDemHelper} demHelper
   * @param {!Uint8Array=} opt_hkdfSalt
   *
   * @return {!Promise.<!HybridDecrypt>}
   */
  static async newInstance(
      recipientPrivateKey, hkdfHash, pointFormat, demHelper, opt_hkdfSalt) {
    if (!recipientPrivateKey) {
      throw new SecurityException('Recipient private key has to be non-null.');
    }
    if (!hkdfHash) {
      throw new SecurityException('HKDF hash algorithm has to be non-null.');
    }
    if (!pointFormat) {
      throw new SecurityException('Point format has to be non-null.');
    }
    if (!demHelper) {
      throw new SecurityException('DEM helper has to be non-null.');
    }

    if (!recipientPrivateKey) {
      throw new SecurityException('Recipient private key has to be non-null.');
    }
    const kemRecipient =
        await EciesHkdfKemRecipient.newInstance(recipientPrivateKey);

    return new EciesAeadHkdfHybridDecrypt(
        recipientPrivateKey, kemRecipient, hkdfHash, pointFormat, demHelper,
        opt_hkdfSalt);
  }

  /**
   * Decrypts ciphertext using opt_contextInfo as info parameter of the
   * underlying HKDF.
   *
   * @override
   */
  async decrypt(ciphertext, opt_contextInfo) {
    if (ciphertext.length < this.headerSize_) {
      throw new SecurityException('Ciphertext is too short.');
    }

    // Split the ciphertext to KEM token and AEAD ciphertext.
    const kemToken = ciphertext.slice(0, this.headerSize_);
    const ciphertextBody =
        ciphertext.slice(this.headerSize_, ciphertext.length);

    const aead = await this.getAead_(kemToken, opt_contextInfo);
    return await aead.decrypt(ciphertextBody);
  }

  /**
   * @private
   * @param {!Uint8Array} kemToken
   * @param {?Uint8Array=} opt_contextInfo
   * @return {!Promise<!Aead>}
   */
  async getAead_(kemToken, opt_contextInfo) {
    // Variable hkdfInfo is not optional for decapsulate method. Thus it should
    // be an empty array in case that it is not defined by the caller of decrypt
    // method.
    if (!opt_contextInfo) {
      opt_contextInfo = new Uint8Array(0);
    }

    const symmetricKey = await this.kemRecipient_.decapsulate(
        kemToken, this.demHelper_.getDemKeySizeInBytes(), this.pointFormat_,
        this.hkdfHash_, opt_contextInfo, this.hkdfSalt_);
    return await this.demHelper_.getAead(symmetricKey);
  }
}

exports = EciesAeadHkdfHybridDecrypt;
