// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// Use the <code>chrome.platformKeys</code> API to access client certificates
// managed by the platform. If the user or policy grants the permission, an
// extension can use such a certficate in its custom authentication protocol.
// E.g. this allows usage of platform managed certificates in third party VPNs
// (see $(ref:vpnProvider chrome.vpnProvider)).
namespace platformKeys {
  [noinline_doc] dictionary Match {
     // The DER encoding of a X.509 certificate.
     ArrayBuffer certificate;

     // The
     // <a href="http://www.w3.org/TR/WebCryptoAPI/#key-algorithm-dictionary">
     // KeyAlgorithm</a> of the certified key. This contains algorithm
     // parameters that are inherent to the key of the certificate (e.g. the key
     // length). Other parameters like the hash function used by the sign
     // function are not included.
     object keyAlgorithm;
  };

  enum ClientCertificateType {
    rsaSign,
    ecdsaSign
  };

  // Analogous to TLS1.1's CertificateRequest.
  // See http://tools.ietf.org/html/rfc4346#section-7.4.4 .
  dictionary ClientCertificateRequest {
    // This field is a list of the types of certificates requested, sorted in
    // order of the server's preference. Only certificates of a type contained
    // in this list will be retrieved. If <code>certificateTypes</code> is the
    // empty list, however, certificates of any type will be returned.
    ClientCertificateType[] certificateTypes;

    // List of distinguished names of certificate authorities allowed by the
    // server. Each entry must be a DER-encoded X.509 DistinguishedName.
    ArrayBuffer[] certificateAuthorities;
  };

  dictionary SelectDetails {
    // Only certificates that match this request will be returned.
    ClientCertificateRequest request;

    // If given, the <code>selectClientCertificates</code> operates on this
    // list. Otherwise, obtains the list of all certificates from the platform's
    // certificate stores that are available to this extensions.
    // Entries that the extension doesn't have permission for or which doesn't
    // match the request, are removed.
    ArrayBuffer[]? clientCerts;

    // If true, the filtered list is presented to the user to manually select a
    // certificate and thereby granting the extension access to the
    // certificate(s) and key(s). Only the selected certificate(s) will be
    // returned. If is false, the list is reduced to all certificates that the
    // extension has been granted access to (automatically or manually).
    boolean interactive;
  };

  dictionary VerificationDetails {
    // Each chain entry must be the DER encoding of a X.509 certificate, the
    // first entry must be the server certificate and each entry must certify
    // the entry preceding it.
    ArrayBuffer[] serverCertificateChain;

    // The hostname of the server to verify the certificate for, e.g. the server
    // that presented the <code>serverCertificateChain</code>.
    DOMString hostname;
  };

  dictionary VerificationResult {
    // The result of the trust verification: true if trust for the given
    // verification details could be established and false if trust is rejected
    // for any reason.
    boolean trusted;

    // If the trust verification failed, this array contains the errors reported
    // by the underlying network layer. Otherwise, this array is empty.
    //
    // <strong>Note:</strong> This list is meant for debugging only and may not
    // contain all relevant errors. The errors returned may change in future
    // revisions of this API, and are not guaranteed to be forwards or backwards
    // compatible.
    DOMString[] debug_errors;
  };

  // |matches|: The list of certificates that match the request, that the
  // extension has permission for and, if <code>interactive</code> is true, that
  // were selected by the user.
  callback SelectCallback = void (Match[] matches);

  // The public and private
  // <a href="http://www.w3.org/TR/WebCryptoAPI/#dfn-CryptoKey">CryptoKey</a>
  // of a certificate which can only be used with
  // $(ref:platformKeys.subtleCrypto).
  // |privateKey|: Might be <code>null</code> if this extension does not have
  //   access to it.
  callback GetKeyPairCallback = void (object publicKey, 
                                      optional object privateKey);

  callback VerificationCallback = void (VerificationResult result);

  interface Functions {
    // This function filters from a list of client certificates the ones that
    // are known to the platform, match <code>request</code> and for which the
    // extension has permission to access the certificate and its private key.
    // If <code>interactive</code> is true, the user is presented a dialog where
    // they can select from matching certificates and grant the extension access
    // to the certificate.
    // The selected/filtered client certificates will be passed to
    // <code>callback</code>.
    [nocompile] static void selectClientCertificates(
        SelectDetails details,
        SelectCallback callback);

    // Passes the key pair of <code>certificate</code> for usage with
    // $(ref:platformKeys.subtleCrypto) to <code>callback</code>.
    // |certificate|: The certificate of a $(ref:Match) returned by
    // $(ref:selectClientCertificates).
    // |parameters|: Determines signature/hash algorithm parameters additionally
    // to the parameters fixed by the key itself. The same parameters are
    // accepted as by WebCrypto's <a
    // href="http://www.w3.org/TR/WebCryptoAPI/#SubtleCrypto-method-importKey">importKey</a>
    // function, e.g. <code>RsaHashedImportParams</code> for a RSASSA-PKCS1-v1_5
    // key. For RSASSA-PKCS1-v1_5 keys, additionally the parameters <code>{
    // "hash": { "name": "none" } }</code> are supported. The sign function will
    // then apply PKCS#1 v1.5 padding and but not hash the given data.
    // <p>Currently, this function only supports the "RSASSA-PKCS1-v1_5"
    // algorithm with one of the hashing algorithms "none", "SHA-1", "SHA-256",
    // "SHA-384", and "SHA-512".</p>
    [nocompile] static void getKeyPair(ArrayBuffer certificate,
                                       object parameters,
                                       GetKeyPairCallback callback);

    // An implementation of WebCrypto's
    // <a href="http://www.w3.org/TR/WebCryptoAPI/#subtlecrypto-interface">
    // SubtleCrypto</a>
    // that allows crypto operations on keys of client certificates that are
    // available to this extension.
    [nocompile] static object subtleCrypto();

    // Checks whether <code>details.serverCertificateChain</code> can be trusted
    // for <code>details.hostname</code> according to the trust settings of the
    // platform.
    // Note: The actual behavior of the trust verification is not fully
    // specified and might change in the future.
    // The API implementation verifies certificate expiration, validates the
    // certification path and checks trust by a known CA.
    // The implementation is supposed to respect the EKU serverAuth and to
    // support subject alternative names.
    static void verifyTLSServerCertificate(VerificationDetails details,
                                           VerificationCallback callback);
  };
};

