// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

// @dart = 2.6

part of dart.io;

/**
 * The object containing the certificates to trust when making
 * a secure client connection, and the certificate chain and
 * private key to serve from a secure server.
 *
 * The [SecureSocket]  and [SecureServerSocket] classes take a SecurityContext
 * as an argument to their connect and bind methods.
 *
 * Certificates and keys can be added to a SecurityContext from either PEM
 * or PKCS12 containers.
 *
 * iOS note: Some methods to add, remove, and inspect certificates are not yet
 * implemented. However, the platform's built-in trusted certificates can
 * be used, by way of [SecurityContext.defaultContext].
 */
abstract class SecurityContext {
  /**
   * Creates a new [SecurityContext].
   *
   * By default, the created [SecurityContext] contains no keys or certificates.
   * These can be added by calling the methods of this class.
   *
   * If `withTrustedRoots` is passed as `true`, the [SecurityContext] will be
   * seeded by the trusted root certificates provided as explained below. To
   * obtain a [SecurityContext] containing trusted root certificates,
   * [SecurityContext.defaultContext] is usually sufficient, and should
   * be used instead. However, if the [SecurityContext] containing the trusted
   * root certificates must be modified per-connection, then `withTrustedRoots`
   * should be used.
   */
  external factory SecurityContext({bool withTrustedRoots: false});

  /**
   * Secure networking classes with an optional `context` parameter
   * use the [defaultContext] object if the parameter is omitted.
   * This object can also be accessed, and modified, directly.
   * Each isolate has a different [defaultContext] object.
   * The [defaultContext] object uses a list of well-known trusted
   * certificate authorities as its trusted roots. On Linux and Windows, this
   * list is taken from Mozilla, who maintains it as part of Firefox. On,
   * MacOS, iOS, and Android, this list comes from the trusted certificates
   * stores built in to the platforms.
   */
  external static SecurityContext get defaultContext;

  /**
   * Sets the private key for a server certificate or client certificate.
   *
   * A secure connection using this SecurityContext will use this key with
   * the server or client certificate to sign and decrypt messages.
   * [file] is the path to a PEM or PKCS12 file containing an encrypted
   * private key, encrypted with [password]. Assuming it is well-formatted, all
   * other contents of [file] are ignored. An unencrypted file can be used,
   * but this is not usual.
   *
   * NB: This function calls [File.readAsBytesSync], and will block on file IO.
   * Prefer using [usePrivateKeyBytes].
   *
   * iOS note: Only PKCS12 data is supported. It should contain both the private
   * key and the certificate chain. On iOS one call to [usePrivateKey] with this
   * data is used instead of two calls to [useCertificateChain] and
   * [usePrivateKey].
   */
  void usePrivateKey(String file, {String password});

  /**
   * Sets the private key for a server certificate or client certificate.
   *
   * Like [usePrivateKey], but takes the contents of the file as a list
   * of bytes.
   */
  void usePrivateKeyBytes(List<int> keyBytes, {String password});

  /**
   * Sets the set of trusted X509 certificates used by [SecureSocket]
   * client connections, when connecting to a secure server.
   *
   * [file] is the path to a PEM or PKCS12 file containing X509 certificates,
   * usually root certificates from certificate authorities. For PKCS12 files,
   * [password] is the password for the file. For PEM files, [password] is
   * ignored. Assuming it is well-formatted, all other contents of [file] are
   * ignored.
   *
   * NB: This function calls [File.readAsBytesSync], and will block on file IO.
   * Prefer using [setTrustedCertificatesBytes].
   *
   * iOS note: On iOS, this call takes only the bytes for a single DER
   * encoded X509 certificate. It may be called multiple times to add
   * multiple trusted certificates to the context. A DER encoded certificate
   * can be obtained from a PEM encoded certificate by using the openssl tool:
   *
   *   $ openssl x509 -outform der -in cert.pem -out cert.der
   */
  void setTrustedCertificates(String file, {String password});

  /**
   * Sets the set of trusted X509 certificates used by [SecureSocket]
   * client connections, when connecting to a secure server.
   *
   * Like [setTrustedCertificates] but takes the contents of the file.
   */
  void setTrustedCertificatesBytes(List<int> certBytes, {String password});

  /**
   * Sets the chain of X509 certificates served by [SecureServerSocket]
   * when making secure connections, including the server certificate.
   *
   * [file] is a PEM or PKCS12 file containing X509 certificates, starting with
   * the root authority and intermediate authorities forming the signed
   * chain to the server certificate, and ending with the server certificate.
   * The private key for the server certificate is set by [usePrivateKey]. For
   * PKCS12 files, [password] is the password for the file. For PEM files,
   * [password] is ignored. Assuming it is well-formatted, all
   * other contents of [file] are ignored.
   *
   * NB: This function calls [File.readAsBytesSync], and will block on file IO.
   * Prefer using [useCertificateChainBytes].
   *
   * iOS note: As noted above, [usePrivateKey] does the job of both
   * that call and this one. On iOS, this call is a no-op.
   */
  void useCertificateChain(String file, {String password});

  /**
   * Sets the chain of X509 certificates served by [SecureServerSocket]
   * when making secure connections, including the server certificate.
   *
   * Like [useCertificateChain] but takes the contents of the file.
   */
  void useCertificateChainBytes(List<int> chainBytes, {String password});

  /**
   * Sets the list of authority names that a [SecureServerSocket] will advertise
   * as accepted when requesting a client certificate from a connecting
   * client.
   *
   * [file] is a PEM or PKCS12 file containing the accepted signing
   * authority certificates - the authority names are extracted from the
   * certificates. For PKCS12 files, [password] is the password for the file.
   * For PEM files, [password] is ignored. Assuming it is well-formatted, all
   * other contents of [file] are ignored.
   *
   * NB: This function calls [File.readAsBytesSync], and will block on file IO.
   * Prefer using [setClientAuthoritiesBytes].
   *
   * iOS note: This call is not supported.
   */
  void setClientAuthorities(String file, {String password});

  /**
   * Sets the list of authority names that a [SecureServerSocket] will advertise
   * as accepted, when requesting a client certificate from a connecting
   * client.
   *
   * Like [setClientAuthorities] but takes the contents of the file.
   */
  void setClientAuthoritiesBytes(List<int> authCertBytes, {String password});

  /**
   * Whether the platform supports ALPN. This always returns true and will be
   * removed in a future release.
   */
  @deprecated
  external static bool get alpnSupported;

  /**
   * Sets the list of application-level protocols supported by a client
   * connection or server connection. The ALPN (application level protocol
   * negotiation) extension to TLS allows a client to send a list of
   * protocols in the TLS client hello message, and the server to pick
   * one and send the selected one back in its server hello message.
   *
   * Separate lists of protocols can be sent for client connections and
   * for server connections, using the same SecurityContext.  The [isServer]
   * boolean argument specifies whether to set the list for server connections
   * or client connections.
   */
  void setAlpnProtocols(List<String> protocols, bool isServer);

  /// Encodes a set of supported protocols for ALPN/NPN usage.
  ///
  /// The `protocols` list is expected to contain protocols in descending order
  /// of preference.
  ///
  /// See RFC 7301 (https://tools.ietf.org/html/rfc7301) for the encoding of
  /// `List<String> protocols`:
  ///     opaque ProtocolName<1..2^8-1>;
  ///
  ///     struct {
  ///         ProtocolName protocol_name_list<2..2^16-1>
  ///     } ProtocolNameList;
  ///
  /// The encoding of the opaque `ProtocolName<lower..upper>` vector is
  /// described in RFC 2246: 4.3 Vectors.
  ///
  /// Note: Even though this encoding scheme would allow a total
  /// `ProtocolNameList` length of 65535, this limit cannot be reached. Testing
  /// showed that more than ~ 2^14  bytes will fail to negotiate a protocol.
  /// We will be conservative and support only messages up to (1<<13)-1 bytes.
  static Uint8List _protocolsToLengthEncoding(List<String> protocols) {
    if (protocols == null || protocols.length == 0) {
      return new Uint8List(0);
    }
    int protocolsLength = protocols.length;

    // Calculate the number of bytes we will need if it is ASCII.
    int expectedLength = protocolsLength;
    for (int i = 0; i < protocolsLength; i++) {
      int length = protocols[i].length;
      if (length > 0 && length <= 255) {
        expectedLength += length;
      } else {
        throw new ArgumentError(
            'Length of protocol must be between 1 and 255 (was: $length).');
      }
    }

    if (expectedLength >= (1 << 13)) {
      throw new ArgumentError(
          'The maximum message length supported is 2^13-1.');
    }

    // Try encoding the `List<String> protocols` array using fast ASCII path.
    var bytes = new Uint8List(expectedLength);
    int bytesOffset = 0;
    for (int i = 0; i < protocolsLength; i++) {
      String proto = protocols[i];

      // Add length byte.
      bytes[bytesOffset++] = proto.length;
      int bits = 0;

      // Add protocol bytes.
      for (int j = 0; j < proto.length; j++) {
        var char = proto.codeUnitAt(j);
        bits |= char;
        bytes[bytesOffset++] = char & 0xff;
      }

      // Go slow case if we have encountered anything non-ascii.
      if (bits > 0x7f) {
        return _protocolsToLengthEncodingNonAsciiBailout(protocols);
      }
    }
    return bytes;
  }

  static Uint8List _protocolsToLengthEncodingNonAsciiBailout(
      List<String> protocols) {
    void addProtocol(List<int> outBytes, String protocol) {
      var protocolBytes = utf8.encode(protocol);
      var len = protocolBytes.length;

      if (len > 255) {
        throw new ArgumentError(
            'Length of protocol must be between 1 and 255 (was: $len)');
      }
      // Add length byte.
      outBytes.add(len);

      // Add protocol bytes.
      outBytes.addAll(protocolBytes);
    }

    List<int> bytes = [];
    for (var i = 0; i < protocols.length; i++) {
      addProtocol(bytes, protocols[i]);
    }

    if (bytes.length >= (1 << 13)) {
      throw new ArgumentError(
          'The maximum message length supported is 2^13-1.');
    }

    return new Uint8List.fromList(bytes);
  }
}
