// 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.Hmac');

const Bytes = goog.require('tink.subtle.Bytes');
const Environment = goog.require('tink.subtle.Environment');
const HmacPureJs = goog.require('tink.subtle.purejs.Hmac');
const InvalidArgumentsException = goog.require('tink.exception.InvalidArgumentsException');
const Mac = goog.require('tink.Mac');
const Validators = goog.require('tink.subtle.Validators');

/**
 * The minimum tag size.
 *
 * @const {number}
 */
const MIN_TAG_SIZE_IN_BYTES = 10;

/**
 * Implementation of HMAC.
 *
 * @implements {Mac}
 * @public
 * @final
 */
class Hmac {
  /**
   * @param {string} hash accepted names are SHA-1, SHA-256 and SHA-512
   * @param {!webCrypto.CryptoKey} key
   * @param {number} tagSize the size of the tag
   */
  constructor(hash, key, tagSize) {
    /** @const @private {string} */
    this.hash_ = hash;

    /** @const @private {number} */
    this.tagSize_ = tagSize;

    /** @const @private {!webCrypto.CryptoKey} */
    this.key_ = key;
  }

  /**
   * @param {string} hash accepted names are SHA-1, SHA-256 and SHA-512
   * @param {!Uint8Array} key
   * @param {number} tagSize the size of the tag
   * @return {!Promise.<!Mac>}
   * @static
   */
  static async newInstance(hash, key, tagSize) {
    Validators.requireUint8Array(key);
    if (!Number.isInteger(tagSize)) {
      throw new InvalidArgumentsException(
          'invalid tag size, must be an integer');
    }
    if (tagSize < MIN_TAG_SIZE_IN_BYTES) {
      throw new InvalidArgumentsException(
          'tag too short, must be at least ' + MIN_TAG_SIZE_IN_BYTES +
          ' bytes');
    }
    switch (hash) {
      case 'SHA-1':
        if (tagSize > 20) {
          throw new InvalidArgumentsException(
              'tag too long, must not be larger than 20 bytes');
        }
        break;
      case 'SHA-256':
        if (tagSize > 32) {
          throw new InvalidArgumentsException(
              'tag too long, must not be larger than 32 bytes');
        }
        break;
      case 'SHA-512':
        if (tagSize > 64) {
          throw new InvalidArgumentsException(
              'tag too long, must not be larger than 64 bytes');
        }
        break;
      default:
        throw new InvalidArgumentsException(hash + ' is not supported');
    }

    // TODO(b/115974209): Add check that key.length > 16.

    if (Environment.IS_WEBCRYPTO_AVAILABLE) {
      const cryptoKey = await self.crypto.subtle.importKey(
          'raw', key,
          {'name': 'HMAC', 'hash': {'name': hash}, 'length': key.length * 8},
          false, ['sign', 'verify']);
      return new Hmac(hash, cryptoKey, tagSize);
    }

    return new HmacPureJs(hash, key, tagSize);
  }

  /**
   * @override
   */
  async computeMac(data) {
    Validators.requireUint8Array(data);
    const tag = await self.crypto.subtle.sign(
        {'name': 'HMAC', 'hash': {'name': this.hash_}}, this.key_, data);
    return new Uint8Array(tag.slice(0, this.tagSize_));
  }

  /**
   * @override
   */
  async verifyMac(tag, data) {
    Validators.requireUint8Array(tag);
    Validators.requireUint8Array(data);
    const computedTag = await this.computeMac(data);
    return Bytes.isEqual(tag, computedTag);
  }
}

exports = Hmac;
