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

/// A Transport Layer Security (TLS) version.
///
/// Only TLS versions supported by `dart:io` are included.
class TlsProtocolVersion {
  /// Transport Layer Security (TLS) Protocol Version 1.2.
  ///
  /// See RFC-5246.
  static const tls1_2 = TlsProtocolVersion._(0x0303);

  /// Transport Layer Security (TLS) Protocol Version 1.3.
  ///
  /// See RFC-8446.
  static const tls1_3 = TlsProtocolVersion._(0x0304);

  final int _version;

  const TlsProtocolVersion._(this._version);

  static TlsProtocolVersion _fromProtocolVersionConstant(int version) =>
      switch (version) {
        0x0303 => tls1_2,
        0x0304 => tls1_3,
        _ => throw ArgumentError.value(version, 'version'),
      };
}

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

  /// The default security context used by most operation requiring one.
  ///
  /// 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 into 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});

  /// Add a certificate to the set of trusted X509 certificates
  /// used by [SecureSocket] client connections.
  ///
  /// [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:
  /// ```bash
  /// $ openssl x509 -outform der -in cert.pem -out cert.der
  /// ```
  void setTrustedCertificates(String file, {String? password});

  /// Add a certificate to the set of trusted X509 certificates
  /// used by [SecureSocket] client connections.
  ///
  /// 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.
  ///
  /// The [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);

  /// If `true`, the [SecurityContext] will allow TLS renegotiation.
  /// Renegotiation is only supported as a client and the HelloRequest must be
  /// received at a quiet point in the application protocol. This is sufficient
  /// to support the legacy use case of requesting a new client certificate
  /// between an HTTP request and response in (unpipelined) HTTP/1.1.
  /// NOTE: Renegotiation is an extremely problematic protocol feature and
  /// should only be used to communicate with legacy servers in environments
  /// where it is known to be safe.
  abstract bool allowLegacyUnsafeRenegotiation;

  /// The minimum TLS version to use when establishing a secure connection.
  ///
  /// If the peer does not support `minimumTlsProtocolVersion` or later
  /// then [SecureSocket.connect] will throw a [TlsException].
  ///
  /// If the value is changed, it will only affect new connections. Existing
  /// connections will continue to use the protocol that was negotiated with the
  /// peer.
  ///
  /// The default value is [TlsProtocolVersion.tls1_2].
  abstract TlsProtocolVersion minimumTlsProtocolVersion;

  /// 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`:
  /// ```plaintext
  /// 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 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 ArgumentError(
          'Length of protocol must be between 1 and 255 (was: $length).',
        );
      }
    }

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

    // Try encoding the `List<String> protocols` array using fast ASCII path.
    var bytes = 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 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 ArgumentError('The maximum message length supported is 2^13-1.');
    }

    return Uint8List.fromList(bytes);
  }
}
