<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta name="Copyright" content="1999 Matt Newman / 2004 Starfish Systems">
<title>TLS (SSL) TCL Commands</title>
<link rel="stylesheet" href="docs.css" type="text/css" media="all">
</head>

<body class="vsc-initialized">

<h2>TCL Tls Extension Documentation</h2>

<dl>
    <dd><a href="#NAME">NAME</a>
    <dl>
	<dd><b>tls</b> - binding to <b>OpenSSL</b> library
	for encrypted socket and I/O channel communications.</dd>
    </dl>
    </dd>
    <dd><a href="#SYNOPSIS">SYNOPSIS</a> </dd>
    <dd><dl>
	<dd><b>package require Tcl</b> <em>?<b>8.5-</b>?</em></dd>
	<dd><b>package require tls</b> <em>?<b>1.8-</b>?</em></dd>
	<dt>&nbsp;</dt>
	<dd><b>tls::init</b> <em>?options?</em> </dd>
	<dd><b>tls::socket</b> <em>?options? host port</em></dd>
	<dd><b>tls::socket</b> <em>?-server command? ?options? port</em></dd>
	<dd><b>tls::handshake</b> <em> channel</em></dd>
	<dd><b>tls::status</b> <em>?-local? channel</em></dd>
	<dd><b>tls::connection</b> <em>channel</em></dd>
	<dd><b>tls::import</b> <em>channel ?options?</em></dd>
	<dd><b>tls::unimport</b> <em>channel</em></dd>
	<dt>&nbsp;</dt>
	<dd><b>tls::ciphers</b> <em>?protocol? ?verbose? ?supported?</em></dd>
	<dd><b>tls::protocols</b></dd>
	<dd><b>tls::version</b></dd>
    </dl></dd>
    <dd><a href="#COMMANDS">COMMANDS</a></dd>
    <dd><a href="#CERTIFICATE VALIDATION">CERTIFICATE VALIDATION</a></dd>
    <dd><a href="#CALLBACK OPTIONS">CALLBACK OPTIONS</a></dd>
    <dd><a href="#DEBUG">DEBUG</a></dd>
    <dd><a href="#HTTPS EXAMPLE">HTTPS EXAMPLE</a></dd>
    <dd><a href="#SPECIAL CONSIDERATIONS">SPECIAL CONSIDERATIONS</a></dd>
    <dd><a href="#SEE ALSO">SEE ALSO</a></dd>
</dl>
<br>

<hr>

<h3><a name="NAME">NAME</a></h3>

<p><strong>tls</strong> - binding to <strong>OpenSSL</strong> library
for encrypted socket and I/O channel communications.</p>
<br>

<hr>

<h3><a name="SYNOPSIS">SYNOPSIS</a></h3>

<p><b>package require Tcl</b> <em>?<b>8.5-</b>?</em><br>
<b>package require tls</b> <em>?<b>1.8-</b>?</em><br>
<br>
<a href="#tls::init"><b>tls::init</b> <i>?options?</i></a><br>
<a href="#tls::socket"><b>tls::socket</b> <i>?options? host port</i><br>
<a href="#tls::socket"><b>tls::socket</b> <i>?-server command? ?options? port</i></a><br>
<a href="#tls::status"><b>tls::status</b> <i>?-local? channel</i></a><br>
<a href="#tls::connection"><b>tls::connection</b> <i>channel</i></a><br>
<a href="#tls::handshake"><b>tls::handshake</b> <i>channel</i></a><br>
<a href="#tls::import"><b>tls::import</b> <i>channel ?options?</i></a><br>
<a href="#tls::unimport"><b>tls::unimport</b> <i>channel</i></a><br>
<br>
<a href="#tls::ciphers"><b>tls::ciphers</b> <i>?protocol? ?verbose? ?supported?</i></a><br>
<a href="#tls::protocols"><b>tls::protocols</b></a><br>
<a href="#tls::version"><b>tls::version</b></a><br>
</p>
<br>

<hr>

<h3><a name="DESCRIPTION">DESCRIPTION</a></h3>

<p>This extension provides TCL script access to secure socket communications
using the Transport Layer Security (TLS) protocol. It provides a generic
binding to <a href="https://www.openssl.org/">OpenSSL</a>, utilizing the
<strong>Tcl_StackChannel</strong> API in TCL 8.4 and higher.
These sockets behave exactly the same as channels created using the built-in
<strong>socket</strong> command, along with additional options for controlling
the SSL/TLS session.
</p>
<br>

<hr>

<h3><a name="COMMANDS">COMMANDS</a></h3>

<p>Typically one would use the <strong>tls::socket </strong>command
which provides compatibility with the native TCL <strong>socket</strong>
command. In such cases <strong>tls::import</strong> should not be
used directly.</p>
<dl>
    <dt><a name="tls::init"><b>tls::init </b><i>?options?</i></a></dt>
    <dd>Optional function to set the default options used by
	<strong>tls::socket</strong>. If you call <strong>tls::import</strong>
	directly, this command has no effect. This command supports all of the
	same options as the <strong>tls::socket</strong> command, though you
	should limit your options to only TLS related ones.</dd>
    <dt>&nbsp;</dt>
    <dt><a name="tls::socket"><b>tls::socket </b><em>?options?
	host port</em></a></dt>
    <dt><b>tls::socket</b><em> ?-server command? ?options? port</em></dt>
    <dd>This is a helper function that utilizes the underlying commands
	(<strong>socket</strong> and <strong>tls::import</strong>) to create
	the connection. It behaves the same as the native TCL <strong>socket</strong>
	command, but also supports the <a href="#tls::import"><strong>tls:import</strong></a>
	command options and one additional option:</dd>
    <dl><blockquote>
	<dt><strong>-autoservername</strong> <em>bool</em></dt>
	<dd>Automatically set the -servername argument to the <em>host</em>
	argument (default is <em>false</em>).</dd>
    </blockquote></dl>

    <dt><a name="tls::import"><b>tls::import </b><i>channel
	?options?</i></a></dt>
    <dd>Add SSL/TLS encryption to a regular TCL channel. It need
	not be a socket, but must provide bi-directional flow. Also
	set session parameters for SSL handshake.</dd>
    <dl><blockquote>
	<dt><strong>-alpn</strong> <em>list</em></dt>
	<dd>List of protocols to offer during Application-Layer
	    Protocol Negotiation (ALPN). For example: <em>h2</em> and
	    <em>http/1.1</em>, but not <em>h3</em> or <em>quic</em>.</dd>
	<dt><strong>-cadir</strong> <em>dir</em></dt>
	<dd>Specifies the directory where the Certificate Authority (CA)
	    certificates are stored. The default is platform specific and can be
	    set at compile time. The default location can be overridden via the
	    <b>SSL_CERT_DIR</b> environment variable.
	    See <a href="#CERTIFICATE VALIDATION">CERTIFICATE VALIDATION</a>.</dd>
	<dt><strong>-cafile </strong><em>filename</em></dt>
	<dd>Specifies the file with the Certificate Authority (CA) certificates
	    to use. The default is <b>cert.pem</b>, in the OpenSSL directory.
	    The default file can be overridden via the <b>SSL_CERT_FILE</b>
	    environment variable.
	    See <a href="#CERTIFICATE VALIDATION">CERTIFICATE VALIDATION</a>.</dd>
	<dt><strong>-castore</strong> <em>URI</em></dt>
	<dd>URI for a Certificate Authority (CA) store, which may be a single
	    container or a catalog of containers. Starting with OpenSSL 3.2 on
	    Windows, set to "org.openssl.winstore://" to use the built-in
	    Windows Cert Store. The Windows cert store only supports root
	    certificate stores.
	    See <a href="#CERTIFICATE VALIDATION">CERTIFICATE VALIDATION</a>.</dd>
	<dt><strong>-certfile</strong> <em>filename</em></dt>
	<dd>Specifies the file with the certificate to use in PEM format.
	    This also contains the public key.</dd>
	<dt><strong>-cert</strong> <em>binary_string</em></dt>
	<dd>Specifies the certificate to use as a DER encoded string (X.509 DER).</dd>
	<dt><strong>-cipher</strong> <em>string</em></dt>
	<dd>Specifies the list of ciphers to use for TLS 1.2 and earlier. String is a
	    colon (":") separated list of ciphers. Ciphers can be combined using the
	    <b>+</b> character. Prefixes can be used to permanently remove ("!"),
	    delete ("-"), or move a cipher to the end of the list ("+"). Keywords
	    <b>@STRENGTH</b> (sort by algorithm key length), <b>@SECLEVEL=</b><i>n</i>
	    (set security level to n), and <b>DEFAULT</b> (use default cipher list,
	    at start only) can also be specified. See OpenSSL documentation for the
	    full list of valid values.</dd>
	<dt><strong>-ciphersuites</strong> <em>string</em></dt>
	<dd>Specifies the list of cipher suites to use for TLS 1.3. String is a colon
	    (":") separated list of cipher suite names.</dd>
	<dt><strong>-command</strong> <em>callback</em></dt>
	<dd>Specifies the callback command to be invoked at several points during the
	    handshake to pass errors, tracing information, and protocol messages.
	    See <a href="#CALLBACK OPTIONS">CALLBACK OPTIONS</a> for more info.</dd>
	<dt><strong>-dhparams </strong><em>filename</em></dt>
	<dd>Specifies the Diffie-Hellman (DH) parameters file.</dd>
	<dt><strong>-keyfile</strong> <em>filename</em></dt>
	<dd>Specifies the private key file. (default is value of -certfile).</dd>
	<dt><strong>-key</strong> <em>filename</em></dt>
	<dd>Specifies the private key to use as a DER encoded string (PKCS#1 DER).</dd>
	<dt><strong>-model</strong> <em>channel</em></dt>
	<dd>Force this channel to share the same <em><strong>SSL_CTX</strong></em>
	    structure as the specified <em>channel</em>, and
	    therefore share callbacks etc.</dd>
	<dt><strong>-password</strong> <em>callback</em></dt>
	<dd>Specifies the callback command to invoke when OpenSSL needs to
	    obtain a password. This is typically used to unlock the private key of
	    a certificate. The callback should return a password string.
	    See <a href="#CALLBACK OPTIONS">CALLBACK OPTIONS</a> for more info.</dd>
	<dt><strong>-post_handshake</strong> <em>bool</em></dt>
	<dd>Allow post-handshake session ticket updates.</dd>
	<dt><strong>-request </strong><em>bool</em></dt>
	<dd>Request a certificate from peer during the SSL handshake. This is
	    needed to do certificate validation. (default is <em>true</em>).
	    See <a href="#CERTIFICATE VALIDATION">CERTIFICATE VALIDATION</a>.</dd>
	<dt><strong>-require</strong> <em>bool</em></dt>
	<dd>Require a valid certificate from peer during SSL handshake. If this
	    is set to true, then <strong>-request</strong> must also be set to
	    true and a either a -cadir, -cafile, -castore, or platform default
	    must be provided in order to validate against. (default is <em>false</em>).
	    See <a href="#CERTIFICATE VALIDATION">CERTIFICATE VALIDATION</a>.</dd>
	<dt><strong>-security_level</strong> <em>integer</em></dt>
	<dd>Specifies the security level (value from 0 to 5). The security level
	    affects the cipher suite encryption algorithms, supported ECC curves,
	    supported signature algorithms, DH parameter sizes, certificate key
	    sizes and signature algorithms. The default is 1 prior to OpenSSL 3.2
	    and 2 thereafter. Level 3 and higher disable support for session
	    tickets and only accept cipher suites that provide forward secrecy.</dd>
	<dt><strong>-server</strong> <em>bool</em></dt>
	<dd>Specifies whether to act as a server and respond with a server
	    handshake when a client connects and provides a client handshake.
	    (default is <em>false</em>)</dd>
	<dt><strong>-servername</strong> <em>host</em></dt>
	<dd>Specify server's hostname. This is used to set the TLS Server Name
	    Indication (SNI) extension. Set this to the expected servername in the
	   server's certificate or one of the subjectAltName alternates.</dd>
	<dt><strong>-session_id</strong> <em>string</em></dt>
	<dd>Specifies the session id to resume session.</dd>
	<dt><strong>-ssl2</strong> <em>bool</em></dt>
	<dd>Enable use of SSL v2. (default is <em>false</em>).
	Note: Recent versions of OpenSSL don't support SSLv2.</dd>
	<dt><strong>-ssl3 </strong><em>bool</em></dt>
	<dd>Enable use of SSL v3. (default is <em>false</em>).
	Note: SSL v3 must also be enabled with a compile time option.</dd>
	<dt>-<strong>tls1</strong> <em>bool</em></dt>
	<dd>Enable use of TLS v1. (default is <em>true</em>).
	Note: TLS 1.0 needs SHA1 to operate, which is only available in
	security level 0 for Open SSL 3.0+.</dd>
	<dt>-<strong>tls1.1</strong> <em>bool</em></dt>
	<dd>Enable use of TLS v1.1 (default is <em>true</em>).
	Note: TLS 1.1 needs SHA1 to operate, which is only available in
	security level 0 for Open SSL 3.0+.</dd>
	<dt>-<strong>tls1.2</strong> <em>bool</em></dt>
	<dd>Enable use of TLS v1.2 (default is <em>true</em>)</dd>
	<dt>-<strong>tls1.3</strong> <em>bool</em></dt>
	<dd>Enable use of TLS v1.3 (default is <em>true</em>)</dd>
	<dt><strong>-validatecommand</strong> <em>callback</em></dt>
	<dd>Specifies the callback command to invoke to validate protocol
	    config parameters during the protocol negotiation phase. This can be
	    used by TCL scripts to perform their own certificate validation to
	    supplement the default validation provided by OpenSSL. The script must
	    return a boolean true to continue the negotiation. See
	    <a href="#CALLBACK OPTIONS">CALLBACK OPTIONS</a> for more info.</dd>
    </blockquote></dl>
    <dt><a name="tls::unimport"><b>tls::unimport </b><i>channel</i></a></dt>
    <dd>Provided for symmetry to <strong>tls::import</strong>, this
	unstacks the encryption of a regular TCL channel. An error
	is thrown if TLS is not the top stacked channel type.</dd>
    <dt>&nbsp;</dt>
    <dt><a name="tls::handshake"><strong>tls::handshake</strong>
	<em>channel</em></a></dt>
    <dd>Forces handshake to take place, and returns 0 if
	handshake is still in progress (non-blocking), or 1 if
	the handshake was successful. If the handshake failed
	this routine will throw an error.</dd>
    <dt>&nbsp;</dt>
    <dt><a name="tls::status"><strong>tls::status</strong>
	<em>?</em><b>-local</b><em>? channel</em></a></dt>
    <dd>Returns the current status of an SSL channel. The result is a list
	of key-value pairs describing the SSL, certificate, and certificate
	verification status. If the SSL handshake has not yet completed,
	an empty list is returned. If <b>-local</b> is specified, then the
	local certificate is used.</dd>
    <blockquote>
    <b>SSL Status</b>
    <dl>
	<dt><strong>alpn</strong> <em>protocol</em></dt>
	<dd>The protocol selected after Application-Layer Protocol
	    Negotiation (ALPN).</dd>
	<dt><strong>cipher</strong> <em>cipher</em></dt>
	<dd>The current cipher in use for the session.</dd>
	<dt><strong>peername</strong> <em>name</em></dt>
	<dd>The peername from the certificate.</dd>
	<dt><strong>protocol</strong> <em>version</em></dt>
	<dd>The protocol version used for the connection:
	    SSL2, SSL3, TLS1, TLS1.1, TLS1.2, TLS1.3, or unknown.</dd>
	<dt><strong>sbits</strong> <em>n</em></dt>
	<dd>The number of bits used for the session key.</dd>
	<dt><strong>signatureHashAlgorithm</strong> <em>algorithm</em></dt>
	<dd>The signature hash algorithm.</dd>
	<dt><strong>signatureType</strong> <em>type</em></dt>
	<dd>The signature type value.</dd>
	<dt><strong>verifyDepth</strong> <em>n</em></dt>
	<dd>Maximum depth for the certificate chain verification.
	    Default is -1, to check all.</dd>
	<dt><strong>verifyMode</strong> <em>list</em></dt>
	<dd>List of certificate verification modes.</dd>
	<dt><strong>verifyResult</strong> <em>result</em></dt>
	<dd>Certificate verification result.</dd>
	<dt><strong>ca_names</strong> <em>list</em></dt>
	<dd>List of the Certificate Authorities used to create the certificate.</dd>
    </dl>
    <b>Certificate Status</b>
    <dl>
	<dt><strong>all</strong> <em>string</em></dt>
	<dd>Dump of all certificate info.</dd>
	<dt><strong>version</strong> <em>value</em></dt>
	<dd>The certificate version.</dd>
	<dt><strong>serialNumber</strong> <em>n</em></dt>
	<dd>The serial number of the certificate as a hex string.</dd>
	<dt><strong>signature</strong> <em>algorithm</em></dt>
	<dd>Cipher algorithm used for certificate signature.</dd>
	<dt><strong>issuer</strong> <em>dn</em></dt>
	<dd>The distinguished name (DN) of the certificate issuer.</dd>
	<dt><strong>notBefore</strong> <em>date</em></dt>
	<dd>The beginning date of the certificate validity.</dd>
	<dt><strong>notAfter</strong> <em>date</em></dt>
	<dd>The expiration date of the certificate validity.</dd>
	<dt><strong>subject</strong> <em>dn</em></dt>
	<dd>The distinguished name (DN) of the certificate subject.
	    Fields include: Common Name (CN), Organization (O), Locality
	    or City (L), State or Province (S), and Country Name (C).</dd>
	<dt><strong>issuerUniqueID</strong> <em>string</em></dt>
	<dd>The issuer unique id.</dd>
	<dt><strong>subjectUniqueID</strong> <em>string</em></dt>
	<dd>The subject unique id.</dd>
	<dt><strong>num_extensions</strong> <em>n</em></dt>
	<dd>Number of certificate extensions.</dd>
	<dt><strong>extensions</strong> <em>list</em></dt>
	<dd>List of certificate extension names.</dd>
	<dt><strong>authorityKeyIdentifier</strong> <em>string</em></dt>
	<dd>(AKI) Key identifier of the Issuing CA certificate that signed
	    the SSL certificate as a hex string. This value matches the SKI
	    value of the Intermediate CA certificate.</dd>
	<dt><strong>subjectKeyIdentifier</strong> <em>string</em></dt>
	<dd>(SKI) Hash of the public key inside the certificate as a hex
	    string. Used to identify certificates that contain a particular
	    public key.</dd>
	<dt><strong>subjectAltName</strong> <em>list</em></dt>
	<dd>List of all of the alternative domain names, sub domains,
	    and IP addresses that are secured by the certificate.</dd>
	<dt><strong>ocsp</strong> <em>list</em></dt>
	<dd>List of all Online Certificate Status Protocol (OCSP) URLs.</dd>
	<dt><strong>certificate</strong> <em>cert</em></dt>
	<dd>The PEM encoded certificate.</dd>
	<dt><strong>signatureAlgorithm</strong> <em>algorithm</em></dt>
	<dd>Cipher algorithm used for the certificate signature.</dd>
	<dt><strong>signatureValue</strong> <em>string</em></dt>
	<dd>Certificate signature as a hex string.</dd>
	<dt><strong>signatureDigest</strong> <em>version</em></dt>
	<dd>Certificate signing digest as a hex string.</dd>
	<dt><strong>publicKeyAlgorithm</strong> <em>algorithm</em></dt>
	<dd>Certificate signature public key algorithm.</dd>
	<dt><strong>publicKey</strong> <em>string</em></dt>
	<dd>Certificate signature public key as a hex string.</dd>
	<dt><strong>bits</strong> <em>n</em></dt>
	<dd>Number of bits used for certificate signature key.</dd>
	<dt><strong>self_signed</strong> <em>boolean</em></dt>
	<dd>Whether the certificate signature is self signed.</dd>
	<dt><strong>sha1_hash</strong> <em>hash</em></dt>
	<dd>The SHA1 hash of the certificate as a hex string.</dd>
	<dt><strong>sha256_hash</strong> <em>hash</em></dt>
	<dd>The SHA256 hash of the certificate as a hex string.</dd>
    </dl>
    </blockquote>

    <dt><a name="tls::connection"><strong>tls::connection</strong>
    <em>channel</em></a></dt>
    <dd>Returns the current connection status of an SSL channel. The
	result is a list of key-value pairs describing the connection.</dd>
    <blockquote>
    <b>SSL Status</b>
    <dl>
	<dt><strong>state</strong> <em>state</em></dt>
	<dd>State of the connection.</dd>
	<dt><strong>servername</strong> <em>name</em></dt>
	<dd>The name of the connected to server.</dd>
	<dt><strong>protocol</strong> <em>version</em></dt>
	<dd>The protocol version used for the connection:
	    SSL2, SSL3, TLS1, TLS1.1, TLS1.2, TLS1.3, or unknown.</dd>
	<dt><strong>renegotiation_allowed</strong> <em>boolean</em></dt>
	<dd>Whether protocol renegotiation is supported or not.</dd>
	<dt><strong>security_level</strong> <em>level</em></dt>
	<dd>The security level used for selection of ciphers, key size, etc.</dd>
	<dt><strong>session_reused</strong> <em>boolean</em></dt>
	<dd>Whether the session has been reused or not.</dd>
	<dt><strong>is_server</strong> <em>boolean</em></dt>
	<dd>Whether the connection is configured as a server (1) or client (0).</dd>
	<dt><strong>compression</strong> <em>mode</em></dt>
	<dd>Compression method.</dd>
	<dt><strong>expansion</strong> <em>mode</em></dt>
	<dd>Expansion method.</dd>
	<dt><strong>caList</strong> <em>list</em></dt>
	<dd>List of Certificate Authorities (CA) for X.509 certificate.</dd>
    </dl>
    <b>Cipher Info</b>
    <dl>
	<dt><strong>cipher</strong> <em>cipher</em></dt>
	<dd>The current cipher in use for the connection.</dd>
	<dt><strong>standard_name</strong> <em>name</em></dt>
	<dd>The standard RFC name of cipher.</dd>
	<dt><strong>algorithm_bits</strong> <em>n</em></dt>
	<dd>The number of processed bits used for cipher.</dd>
	<dt><strong>secret_bits</strong> <em>n</em></dt>
	<dd>The number of secret bits used for cipher.</dd>
	<dt><strong>min_version</strong> <em>version</em></dt>
	<dd>The minimum protocol version for cipher.</dd>
	<dt><strong>cipher_is_aead</strong> <em>boolean</em></dt>
	<dd>Whether the cipher is Authenticated Encryption with
	    Associated Data (AEAD).</dd>
	<dt><strong>cipher_id</strong> <em>id</em></dt>
	<dd>The OpenSSL cipher id.</dd>
	<dt><strong>description</strong> <em>string</em></dt>
	<dd>A text description of the cipher.</dd>
	<dt><strong>handshake_digest</strong> <em>boolean</em></dt>
	<dd>Digest used during handshake.</dd>
    </dl>
    <b>Session Info</b>
    <dl>
	<dt><strong>alpn</strong> <em>protocol</em></dt>
	<dd>The protocol selected after Application-Layer Protocol
	    Negotiation (ALPN).</dd>
	<dt><strong>resumable</strong> <em>boolean</em></dt>
	<dd>Whether the session can be resumed or not.</dd>
	<dt><strong>start_time</strong> <em>seconds</em></dt>
	<dd>Time since session started in seconds since epoch.</dd>
	<dt><strong>timeout</strong> <em>seconds</em></dt>
	<dd>Max duration of session in seconds before time-out.</dd>
	<dt><strong>lifetime</strong> <em>seconds</em></dt>
	<dd>Session ticket lifetime hint in seconds.</dd>
	<dt><strong>session_id</strong> <em>binary_string</em></dt>
	<dd>Unique session id for use in resuming the session.</dd>
	<dt><strong>session_ticket</strong> <em>binary_string</em></dt>
	<dd>Unique session ticket for use in resuming the session.</dd>
	<dt><strong>ticket_app_data</strong> <em>binary_string</em></dt>
	<dd>Unique session ticket application data.</dd>
	<dt><strong>master_key</strong> <em>binary_string</em></dt>
	<dd>Unique session master key.</dd>
	<dt><strong>session_cache_mode</strong> <em>mode</em></dt>
	<dd>Server cache mode (client, server, or both).</dd>
    </dl>
    </blockquote>

    <dt><a name="tls::ciphers"><strong>tls::ciphers</strong>
	<em>?protocol? ?verbose? ?supported?</em></a></dt>
    <dd>Without any args, returns a list of all symmetric ciphers for use
	with the <strong>-cipher</strong> option. With <em>protocol</em>,
	only the ciphers supported for that protocol are returned. See
	<a href="#tls::protocols"><strong>tls::protocols</strong></a> command
	for the supported protocols. If <em>verbose</em> is specified as true
	then a verbose, human readable list is returned with additional
	information on the cipher. If <em>supported</em> is specified as true,
	then only the ciphers supported for protocol will be listed.</dd>
    <dt>&nbsp;</dt>
    <dt><a name="tls::protocols"><strong>tls::protocols</strong></a></dt>
    <dd>Returns a list of the supported SSL/TLS protocols. Valid values are:
	<b>ssl2</b>, <b>ssl3</b>, <b>tls1</b>, <b>tls1.1</b>, <b>tls1.2</b>,
	and <b>tls1.3</b>. Exact list depends on OpenSSL version and
	compile time flags.</dd>
    <dt>&nbsp;</dt>
    <dt><a name="tls::version"><strong>tls::version</strong></a></dt>
    <dd>Returns the OpenSSL version string.</dd>
</dl>
<br>

<hr>

<h3><a name="CERTIFICATE VALIDATION">CERTIFICATE VALIDATION</a></h3>

<h4>Summary of command line options:</h4>
<p>The following options are used for certificate validation:</p>
<ul>
<li>The <b>-cadir</b> option specifies the directory where the Certificate
Authority (CA) certificates are stored. The default is platform specific, but
is usually "/etc/ssl/certs" on Linux/Unix systems. The default location can be
overridden via the <b>SSL_CERT_DIR</b> environment variable.</li>
<li>The <b>-cafile </b> option specifies the file that contains all of the
Certificate Authority (CA) certificates in the PEM file format. The default is
<b>cert.pem</b>, in the OpenSSL directory. On Linux/Unix systems, this is
usually "/etc/ssl/ca-bundle.pem". The default file can be overridden via the
<b>SSL_CERT_FILE</b> environment variable.</li>
<li>The <b>-castore</b> option contains the URI to the Certificate Authority
(CA) store, which may be a single container or a catalog of containers.
Starting with OpenSSL 3.2 on Windows, set this to "org.openssl.winstore://" to
use the built-in Windows Certificate Store. The Windows cert store only
supports root certificate stores.</li>
<li>The <b>-request</b> option is used to request the server send its
certificate chain as part of the connection negotiation process. This is
needed to do certificate validation. The default is true. In addition, the
client can manually inspect and accept or reject each certificate using the
<b>-validatecommand</b> option.</li>
<li>The <b>-require</b> option is used to require certificate validation be
performed as part of the connection negotiation process. A valid CA directory,
file, or store must be present for this to work.</li>
</ul>

<br>
<h4>When are command line options needed:</h4>
<p>
By default, a client TLS connection does NOT validate the server certificate
chain. This limitation is due to the lack of a common cross platform
database of Certificate Authority (CA) provided certificates to validate
against. Many Linux systems natively support OpenSSL and thus have these
certificates installed as part of the OS, but MacOS and Windows do not. In
order to use the <b>-require</b> option, one of the following must be true:</p>
<ul>
<li>On Linux and Unix systems with OpenSSL already installed, if the CA
certificates are stored in the standard locations, or the <b>SSL_CERT_DIR</b>
or <b>SSL_CERT_FILE</b> env vars are set, then no other options are needed.</li>

<li>If OpenSSL is not installed in the default location, or when using Mac OS
or Windows and OpenSSL is installed, the <b>SSL_CERT_DIR</b> and/or 
<b>SSL_CERT_FILE</b> env vars or the <b>-cadir</b> and/or <b>-cafile</b>
 options must be defined.</li>

<li>On Windows, starting in OpenSSL 3.2, it is now possible to access the
built-in Windows Certificate Store from OpenSSL. This can be achieved by
setting the <b>-castore</b> option to "<b>org.openssl.winstore://</b>".</li>

<li>If OpenSSL is not installed, the CA certificates must be downloaded and
installed with the user software. The CURL team makes them available at
<a href="https://curl.se/docs/caextract.html">CA certificates extracted
from Mozilla</a> in the <b>cacert.pem</b> file. You must then either
set the <b>SSL_CERT_DIR</b> and/or <b>SSL_CERT_FILE</b> env vars or the
<b>-cadir</b> or <b>-cafile</b> options must be set to the file's install
location. It is your responsibility to keep this file up to date.</li>
</ul>
<br>

<hr>

<h3><a name="CALLBACK OPTIONS">CALLBACK OPTIONS</a></h3>

<p>
As indicated above, individual channels can be given their own callbacks
to handle intermediate processing by the OpenSSL library, using the
<strong>-command</strong>, <strong>-password</strong>, and
<strong>-validate_command</strong> options passed to either of
<strong>tls::socket</strong> or <strong>tls::import</strong>.
Unlike previous versions of TCL TLS, only if the callback generates an error,
will the <b>bgerror</b> command will be invoked with the error information.
</p>

<dl>
    <dt><strong>-command</strong> <em>callback</em></dt>
    <dd>
	Invokes the specified <em>callback</em> script at several points
	during the OpenSSL handshake and use. See below for the possible
	arguments passed to the callback script. Values returned from the
	callback are ignored.
    <br>
    <dl>
	<dt>
	<strong>error</strong> <em>channelId message</em>
	</dt>
	<dd>
	    This form of callback is invoked whenever an error occurs during the
	    initial connection, handshake, or I/O operations. The <em>message</em>
	    argument can be from the Tcl_ErrnoMsg, OpenSSL function
	    <code>ERR_reason_error_string()</code>, or a custom message.
	</dd>
	<br>
	<dt>
	    <strong>info</strong> <em>channelId major minor message type</em>
	</dt>
	<dd>
	     This form of callback is invoked by the OpenSSL function
	    <code>SSL_set_info_callback()</code> during the initial connection
	    and handshake operations. The <em>type</em> argument is new for
	    TLS 1.8. The arguments are:
	<br>
	<ul>
	<li>Possible values for <em>major</em> are:
	    <code>handshake, alert, connect, accept</code>.</li>
	<li>Possible values for <em>minor</em> are:
	    <code>start, done, read, write, loop, exit</code>.</li>
	<li>The <em>message</em> argument is a descriptive string which may
	    be generated either by <code>SSL_state_string_long()</code> or by
	    <code>SSL_alert_desc_string_long()</code>, depending on the context.</li>
	<li>For alerts, the possible values for <em>type</em> are:
	    <code>warning, fatal, and unknown</code>. For others,
	    <code>info</code> is used.</li>
	</ul>
	</dd>
	<dt>
	<strong>message</strong> <em>channelId direction version content_type message</em>
	</dt>
	<dd>
	    This form of callback is invoked by the OpenSSL function
	    <code>SSL_set_msg_callback()</code> whenever a message is sent or
	    received during the initial connection, handshake, or I/O operations.
	    It is only available when OpenSSL is complied with the
	    <em>enable-ssl-trace</em> option. Arguments are: <em>direction</em>
	    is <b>Sent</b> or <b>Received</b>, <em>version</em> is the protocol
	    version, <em>content_type</em> is the message content type, and
	    <em>message</em> is more info from the <code>SSL_trace</code> API.
	    This callback is new for TLS 1.8.
	</dd>
	<br>
	<dt>
	<strong>session</strong> <em>channelId session_id ticket lifetime</em>
	</dt>
	<dd>
	    This form of callback is invoked by the OpenSSL function
	    <code>SSL_CTX_sess_set_new_cb()</code> whenever a new session id is
	    sent by the server during the initial connection and handshake, but
	    can also be received later if the <b>-post_handshake</b> option is
	    used. Arguments are: <em>session_id</em> is the current
	    session identifier, <em>ticket</em> is the session ticket info, and
	    <em>lifetime</em> is the the ticket lifetime in seconds.
	    This callback is new for TLS 1.8.
	</dd>
    </dl>
    </dd>
</dl>
<br>
<dl>
    <dt><strong>-password</strong> <em>callback</em></dt>
    <dd>
	Invokes the specified <em>callback</em> script when OpenSSL needs to
	obtain a password. See below for the possible arguments passed to
	the callback script. See below for valid return values.
	<br>
	<dl>
	    <dt>
	    <strong>password</strong> <em>rwflag size</em>
	    </dt>
	    <dd>
		Invoked when loading or storing a PEM certificate with encryption.
		Where <em>rwflag</em> is 0 for reading/decryption or 1 for
		writing/encryption (can prompt user to confirm) and <em>size</em> is
		the max password length in bytes. The callback should return the
		password as a string. Both arguments are new for TLS 1.8.
	    </dd>
	</dl>
    </dd>
</dl>
<br>
<dl>
    <dt><strong>-validatecommand</strong> <em>callback</em></dt>
    <dd>
	Invokes the specified <em>callback</em> script during handshake in
	order to validate the provided value(s). See below for the possible
	arguments passed to the callback script. If not specified, OpenSSL
	will accept valid certificates and extensions.
	To reject the value and abort the connection, the callback should return 0.
	To accept the value and continue the connection, it should return 1.
	To reject the value, but continue the connection, it should return 2.
	<br>
	<dl>
	    <dt>
		<strong>alpn</strong> <em>channelId protocol match</em>
		</dt>
	    <dd>
		For servers, this form of callback is invoked when the client ALPN
		extension is received. If <em>match</em> is true, <em>protocol</em>
		is the first <b>-alpn</b> option specified protocol common to both
		the client and server. If not, the first client specified protocol is
		used. It is called after the hello and ALPN callbacks.
		This callback is new for TLS 1.8.
	    </dd>
	    <br>
	    <dt>
		<strong>hello</strong> <em>channelId servername</em>
	    </dt>
	    <dd>
		For servers, this form of callback is invoked during client hello
		message processing. The purpose is so the server can select the
		appropriate certificate to present to the client, and to make other
		configuration adjustments relevant to that server name and its
		configuration. It is called before the SNI and ALPN callbacks.
		This callback is new for TLS 1.8.
	    </dd>
	    <br>
	    <dt>
		<strong>sni</strong> <em>channelId servername</em>
	    </dt>
	    <dd>
		For servers, this form of callback is invoked when the Server Name
		Indication (SNI) extension is received. The <em>servername</em>
		argument is the client provided server name in the <b>-servername</b>
		option. The purpose is so when a server supports multiple names, the
		right certificate can be used. It is called after the hello callback
		but before the ALPN callback.
		This callback is new for TLS 1.8.
	    </dd>
	    <br>
	    <dt>
		<strong>verify</strong> <em>channelId depth cert status error</em>
	    </dt>
	    <dd>
		This form of callback is invoked by OpenSSL when a new certificate
		is received from the peer. It allows the client to check the
		certificate verification results and choose whether to continue
		or not. It is called for each certificate in the certificate chain.
		<ul>
		<li>The <em>depth</em> argument is the integer depth of the
		certificate in the certificate chain, where 0 is the peer certificate
		and higher values going up to the Certificate Authority (CA).</li>
		<li>The <em>cert</em> argument is a list of key-value pairs similar
		to those returned by
		<a href="#tls::status"><strong>tls::status</strong></a>.</li>
		<li>The <em>status</em> argument is the boolean validity of the
		current certificate where 0 is invalid and 1 is valid.</li>
		<li>The <em>error</em> argument is the error message, if any, generated
		by <code>X509_STORE_CTX_get_error()</code>.</li>
		</ul>
	    </dd>
	    <br>
	</dl>
    </dd>
</dl>

<p>
Reference implementations of these callbacks are provided in the
distribution as <strong>tls::callback</strong>, <strong>tls::password</strong>,
and <strong>tls::validate_command</strong> respectively. Note that these are
<em>sample</em> implementations only. In a more realistic deployment
you would specify your own callback scripts on each TLS channel using the
<strong>-command</strong>, <strong>-password</strong>, and
<strong>-validate_command</strong> options.
</p>
<p>
The default behavior when the <strong>-command</strong> and <strong>-validate_command</strong>
options are not specified is for TLS to process the associated library callbacks
internally. The default behavior when the <strong>-password</strong> option is not
specified is for TLS to process the associated library callbacks by attempting
to call <strong>tls::password</strong>.
The difference between these two behaviors is a consequence of maintaining
compatibility with earlier implementations.
</p>
<p>
<em>
The use of the reference callbacks <strong>tls::callback</strong>,
<strong>tls::password</strong>, and <strong>tls::validate_command</strong>
is not recommended. They may be removed from future releases.
</em>
</p>
<br>

<hr>

<h3><a name="DEBUG">DEBUG</a></h3>

<p>For most debugging needs, the <b>-callback</b> option can be used to provide
sufficient insight and information on the TLS handshake and progress. If further
troubleshooting insight is needed, the compile time option <b>--enable-debug</b>
can be used to get detailed execution flow status.</p>

<p>TLS key logging can be enabled by setting the environment variable
<b>SSLKEYLOGFILE</b> to the name of the file to log to. Then whenever TLS
key material is generated or received it will be logged to the file. This
is useful for logging key data for network logging tools to use to
decrypt the data.</p>

<p>The <strong>tls::debug</strong> variable provides some additional
control over these reference callbacks. Its value is zero by default.
Higher values produce more diagnostic output, and will also force the
verify method in <strong>tls::callback</strong> to accept the
certificate, even when it is invalid if the <b>tls::validate_command</b>
callback is used for the <b>-validatecommand</b> option.</p>

<p><em>The use of the variable <strong>tls::debug</strong> is not recommended.
It may be removed from future releases.</em></p>

<h4><a name="DEBUG_EXAMPLES">Debug Examples</a></h4>

<p>These examples use the default Unix platform SSL certificates. For standard
installations, -cadir and -cafile should not be needed. If your certificates
are in non-standard locations, update -cadir or use -cafile as needed.</p>
<br>

<p>Example #1: Use HTTP package</p>
<pre><code>
package require http
package require tls
set url "https://www.tcl.tk/"

http::register https 443 [list ::tls::socket -autoservername true -require true -cadir /etc/ssl/certs \
    -command ::tls::callback -password ::tls::password -validatecommand ::tls::validate_command]

# Check for error
set token [http::geturl $url]
if {[http::status $token] ne "ok"} {
    puts [format "Error %s" [http::status $token]]
}

# Get web page
set data [http::data $token]
puts [string length $data]

# Cleanup
::http::cleanup $token
</code></pre>

<p>Example #2: Use raw socket</p>
<pre><code>
package require tls

set url "www.tcl-lang.org"
set port 443

set ch [tls::socket -autoservername 1 -servername $url -request 1 -require 1 \
    -alpn {http/1.1} -cadir /etc/ssl/certs -command ::tls::callback \
    -password ::tls::password -validatecommand ::tls::validate_command $url $port]
chan configure $ch -buffersize 65536
tls::handshake $ch

puts $ch "GET / HTTP/1.1"
flush $ch
after 500
set data [read $ch]

array set status [tls::status $ch]
array set conn [tls::connection $ch]
array set chan [chan configure $ch]
close $ch
parray status
parray conn
parray chan
</code></pre>
<br>

<hr>

<h3><a name="HTTPS EXAMPLE">HTTPS EXAMPLE</a></h3>

<p>These examples use the default Unix platform SSL certificates. For standard
installations, -cadir and -cafile should not be needed. If your certificates
are in non-standard locations, update -cadir or use -cafile as needed.</p>

<p>Example #1: Get web page</p>
<pre><code>
package require http
package require tls
set url "https://www.tcl.tk/"

http::register https 443 [list ::tls::socket -autoservername true -require true -cadir /etc/ssl/certs]

# Check for error
set token [http::geturl $url]
if {[http::status $token] ne "ok"} {
    puts [format "Error %s" [http::status $token]]
}

# Get web page
set data [http::data $token]
puts $data

# Cleanup
::http::cleanup $token
</code></pre>

<p>Example #2: Download file</p>
<pre><code>
package require http
package require tls

set url "https://wiki.tcl-lang.org/sitemap.xml"
set filename [file tail $url]

http::register https 443 [list ::tls::socket -autoservername true -require true -cadir /etc/ssl/certs]

# Get file
set ch [open $filename wb]
set token [::http::geturl $url -blocksize 65536 -channel $ch]

# Cleanup
close $ch
::http::cleanup $token
</code></pre>
<br>

<hr>

<h3><a name="SPECIAL CONSIDERATIONS">SPECIAL CONSIDERATIONS</a></h3>

<p>The capabilities of this package can vary enormously based upon how the
linked to OpenSSL library was configured and built. New versions may obsolete
older protocol versions, add or remove ciphers, change default values, etc.
Use the <strong>tls::protocols</strong> commands to obtain the supported
protocol versions.</p>

<hr>

<h3><a name="SEE ALSO">SEE ALSO</a></h3>

<p><strong>socket</strong>, <strong>fileevent</strong>, <strong>http</strong>,
<a href="https://www.openssl.org/"><strong>OpenSSL</strong></a></p>

<hr>

<pre>
Copyright &copy; 1999 Matt Newman.
Copyright &copy; 2004 Starfish Systems.
Copyright &copy; 2023 Brian O'Hagan.
</pre>
</body>
</html>
