/*
 * Copyright (C) 2013 Google Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 *     * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above
 * copyright notice, this list of conditions and the following disclaimer
 * in the documentation and/or other materials provided with the
 * distribution.
 *     * Neither the name of Google Inc. nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#ifndef THIRD_PARTY_BLINK_PUBLIC_PLATFORM_WEB_CRYPTO_H_
#define THIRD_PARTY_BLINK_PUBLIC_PLATFORM_WEB_CRYPTO_H_

#include "base/single_thread_task_runner.h"
#include "third_party/blink/public/platform/web_common.h"
#include "third_party/blink/public/platform/web_crypto_algorithm.h"
#include "third_party/blink/public/platform/web_crypto_key.h"
#include "third_party/blink/public/platform/web_private_ptr.h"
#include "third_party/blink/public/platform/web_string.h"
#include "third_party/blink/public/platform/web_vector.h"

#include <memory>

#if INSIDE_BLINK
#include "base/memory/scoped_refptr.h"
#include "third_party/blink/renderer/platform/heap/handle.h"  // nogncheck
#endif

namespace blink {

class CryptoResult;
class CryptoResultCancel;
class WebString;

enum WebCryptoErrorType {
  kWebCryptoErrorTypeType,
  kWebCryptoErrorTypeNotSupported,
  kWebCryptoErrorTypeSyntax,
  kWebCryptoErrorTypeInvalidAccess,
  kWebCryptoErrorTypeData,
  kWebCryptoErrorTypeOperation,
};

class WebCryptoResult {
 public:
  WebCryptoResult(const WebCryptoResult& o) { Assign(o); }

  ~WebCryptoResult() { Reset(); }

  WebCryptoResult& operator=(const WebCryptoResult& o) {
    Assign(o);
    return *this;
  }

  // Note that WebString is NOT safe to pass across threads.
  //
  // Error details are surfaced in an exception, and MUST NEVER reveal any
  // secret information such as bytes of the key or plain text. An
  // appropriate error would be something like:
  //   "iv must be 16 bytes long".
  BLINK_PLATFORM_EXPORT void CompleteWithError(WebCryptoErrorType,
                                               const WebString&);

  // Makes a copy of the input data given as a pointer and byte length.
  BLINK_PLATFORM_EXPORT void CompleteWithBuffer(const void*, unsigned);
  BLINK_PLATFORM_EXPORT void CompleteWithJson(const char* utf8_data,
                                              unsigned length);
  BLINK_PLATFORM_EXPORT void CompleteWithBoolean(bool);
  BLINK_PLATFORM_EXPORT void CompleteWithKey(const WebCryptoKey&);
  BLINK_PLATFORM_EXPORT void CompleteWithKeyPair(
      const WebCryptoKey& public_key,
      const WebCryptoKey& private_key);

  // Returns true if the underlying operation was cancelled.
  // This method can be called from any thread.
  BLINK_PLATFORM_EXPORT bool Cancelled() const;

#if INSIDE_BLINK
  BLINK_PLATFORM_EXPORT WebCryptoResult(CryptoResult*,
                                        scoped_refptr<CryptoResultCancel>);
#endif

 private:
  BLINK_PLATFORM_EXPORT void Reset();
  BLINK_PLATFORM_EXPORT void Assign(const WebCryptoResult&);

  WebPrivatePtr<CryptoResult, kWebPrivatePtrDestructionCrossThread> impl_;
  WebPrivatePtr<CryptoResultCancel, kWebPrivatePtrDestructionCrossThread>
      cancel_;
};

class WebCrypto {
 public:
  // WebCrypto is the interface for starting one-shot cryptographic
  // operations.
  //
  // -----------------------
  // Completing the request
  // -----------------------
  //
  // Implementations signal completion by calling one of the methods on
  // "result". Only a single result/error should be set for the request.
  // Different operations expect different result types based on the
  // algorithm parameters; see the Web Crypto standard for details.
  //
  // The result can be set either synchronously while handling the request,
  // or asynchronously after the method has returned. When completing
  // asynchronously make a copy of the WebCryptoResult and call it from the
  // |result_task_runner| TaskRunner.
  //
  // If the request was cancelled it is not necessary for implementations to
  // set the result.
  //
  // -----------------------
  // Threading
  // -----------------------
  //
  // The WebCrypto interface will be called from blink threads (main or
  // web worker). All communication back to Blink must be on this same thread
  // (|result_task_runner|).
  //
  // Notably:
  //
  //   * The WebCryptoResult can be copied between threads, however all
  //     methods other than the destructor must be called from the origin
  //     Blink thread (|result_task_runner|).
  //
  //   * WebCryptoKey and WebCryptoAlgorithm ARE threadsafe. They can be
  //     safely copied between threads and accessed. Copying is cheap because
  //     they are internally reference counted.
  //
  // -----------------------
  // Inputs
  // -----------------------
  //
  //   * Data buffers are transfered as WebVectors. Implementations are free
  //     to re-use or transfer their storage.
  //
  //   * All WebCryptoKeys are guaranteeed to be !IsNull().
  //
  //   * All WebCryptoAlgorithms are guaranteed to be !IsNull()
  //
  //   * Look to the Web Crypto spec for an explanation of the parameter. The
  //     method names here have a 1:1 correspondence with those of
  //     crypto.subtle, with the exception of "verify" which is here called
  //     "verifySignature".
  //
  // -----------------------
  // Guarantees on input validity
  // -----------------------
  //
  // Implementations MUST carefully sanitize algorithm inputs before using
  // them, as they come directly from the user. Few checks have been done on
  // algorithm parameters prior to passing to the embedder.
  //
  // Only the following checks can be assumed as having already passed:
  //
  //  * The key is extractable when calling into ExportKey/WrapKey.
  //  * The key usages permit the operation being requested.
  //  * The key's algorithm matches that of the requested operation.
  //
  virtual void Encrypt(
      const WebCryptoAlgorithm&,
      const WebCryptoKey&,
      WebVector<unsigned char> data,
      WebCryptoResult result,
      scoped_refptr<base::SingleThreadTaskRunner> task_runner) {
    result.CompleteWithError(kWebCryptoErrorTypeNotSupported, "");
  }
  virtual void Decrypt(
      const WebCryptoAlgorithm&,
      const WebCryptoKey&,
      WebVector<unsigned char> data,
      WebCryptoResult result,
      scoped_refptr<base::SingleThreadTaskRunner> task_runner) {
    result.CompleteWithError(kWebCryptoErrorTypeNotSupported, "");
  }
  virtual void Sign(const WebCryptoAlgorithm&,
                    const WebCryptoKey&,
                    WebVector<unsigned char> data,
                    WebCryptoResult result,
                    scoped_refptr<base::SingleThreadTaskRunner> task_runner) {
    result.CompleteWithError(kWebCryptoErrorTypeNotSupported, "");
  }
  virtual void VerifySignature(
      const WebCryptoAlgorithm&,
      const WebCryptoKey&,
      WebVector<unsigned char> signature,
      WebVector<unsigned char> data,
      WebCryptoResult result,
      scoped_refptr<base::SingleThreadTaskRunner> task_runner) {
    result.CompleteWithError(kWebCryptoErrorTypeNotSupported, "");
  }
  virtual void Digest(const WebCryptoAlgorithm&,
                      WebVector<unsigned char> data,
                      WebCryptoResult result,
                      scoped_refptr<base::SingleThreadTaskRunner> task_runner) {
    result.CompleteWithError(kWebCryptoErrorTypeNotSupported, "");
  }
  virtual void GenerateKey(
      const WebCryptoAlgorithm&,
      bool extractable,
      WebCryptoKeyUsageMask,
      WebCryptoResult result,
      scoped_refptr<base::SingleThreadTaskRunner> task_runner) {
    result.CompleteWithError(kWebCryptoErrorTypeNotSupported, "");
  }
  virtual void ImportKey(
      WebCryptoKeyFormat,
      WebVector<unsigned char> key_data,
      const WebCryptoAlgorithm&,
      bool extractable,
      WebCryptoKeyUsageMask,
      WebCryptoResult result,
      scoped_refptr<base::SingleThreadTaskRunner> task_runner) {
    result.CompleteWithError(kWebCryptoErrorTypeNotSupported, "");
  }
  virtual void ExportKey(
      WebCryptoKeyFormat,
      const WebCryptoKey&,
      WebCryptoResult result,
      scoped_refptr<base::SingleThreadTaskRunner> task_runner) {
    result.CompleteWithError(kWebCryptoErrorTypeNotSupported, "");
  }
  virtual void WrapKey(
      WebCryptoKeyFormat,
      const WebCryptoKey& key,
      const WebCryptoKey& wrapping_key,
      const WebCryptoAlgorithm&,
      WebCryptoResult result,
      scoped_refptr<base::SingleThreadTaskRunner> task_runner) {
    result.CompleteWithError(kWebCryptoErrorTypeNotSupported, "");
  }
  virtual void UnwrapKey(
      WebCryptoKeyFormat,
      WebVector<unsigned char> wrapped_key,
      const WebCryptoKey&,
      const WebCryptoAlgorithm& unwrap_algorithm,
      const WebCryptoAlgorithm& unwrapped_key_algorithm,
      bool extractable,
      WebCryptoKeyUsageMask,
      WebCryptoResult result,
      scoped_refptr<base::SingleThreadTaskRunner> task_runner) {
    result.CompleteWithError(kWebCryptoErrorTypeNotSupported, "");
  }
  virtual void DeriveBits(
      const WebCryptoAlgorithm&,
      const WebCryptoKey&,
      unsigned length,
      WebCryptoResult result,
      scoped_refptr<base::SingleThreadTaskRunner> task_runner) {
    result.CompleteWithError(kWebCryptoErrorTypeNotSupported, "");
  }
  virtual void DeriveKey(
      const WebCryptoAlgorithm& algorithm,
      const WebCryptoKey& base_key,
      const WebCryptoAlgorithm& import_algorithm,
      const WebCryptoAlgorithm& key_length_algorithm,
      bool extractable,
      WebCryptoKeyUsageMask,
      WebCryptoResult result,
      scoped_refptr<base::SingleThreadTaskRunner> task_runner) {
    result.CompleteWithError(kWebCryptoErrorTypeNotSupported, "");
  }

  // -----------------------
  // Structured clone
  // -----------------------
  //
  // DeserializeKeyForClone() and SerializeKeyForClone() are used for
  // implementing structured cloning of WebCryptoKey.
  //
  // Blink is responsible for saving and restoring all of the attributes of
  // WebCryptoKey EXCEPT for the actual key data:
  //
  // In other words, Blink takes care of serializing:
  //   * Key usages
  //   * Key extractability
  //   * Key algorithm
  //   * Key type (public, private, secret)
  //
  // The embedder is responsible for saving the key data itself.
  //
  // Visibility of the serialized key data:
  //
  // The serialized key data will NOT be visible to web pages. So if the
  // serialized format were to include key bytes as plain text, this wouldn't
  // make it available to web pages.
  //
  // Longevity of the key data:
  //
  // The serialized key data is intended to be long lived (years) and MUST
  // be using a stable format. For instance a key might be persisted to
  // IndexedDB and should be able to be deserialized correctly in the
  // future.
  //
  // Error handling and asynchronous completion:
  //
  // Serialization/deserialization must complete synchronously, and will
  // block the JavaScript thread.
  //
  // The only reasons to fail serialization/deserialization are:
  //   * Key serialization not yet implemented
  //   * The bytes to deserialize were corrupted

  // Creates a new key given key data which was written using
  // SerializeKeyForClone(). Returns true on success.
  virtual bool DeserializeKeyForClone(const WebCryptoKeyAlgorithm&,
                                      WebCryptoKeyType,
                                      bool extractable,
                                      WebCryptoKeyUsageMask,
                                      const unsigned char* key_data,
                                      unsigned key_data_size,
                                      WebCryptoKey&) {
    return false;
  }

  // Writes the key data into the given WebVector.
  // Returns true on success.
  virtual bool SerializeKeyForClone(const WebCryptoKey&,
                                    WebVector<unsigned char>&) {
    return false;
  }

 protected:
  virtual ~WebCrypto() = default;
};

}  // namespace blink

#endif  // THIRD_PARTY_BLINK_PUBLIC_PLATFORM_WEB_CRYPTO_H_
