// 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.

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);
  }
}
