Skip to content
/ tclmtls Public

tclmtls package to provide SSL/TLS support in Tcl

License

Notifications You must be signed in to change notification settings

chpock/tclmtls

Repository files navigation

Introduction

This Tcl package provides an extension which implements Transport Layer Security (TLS) over Transmission Control Protocol (TCP) network communication channels.

Why?

Usual Tcl package for SSL/TLS communication channels is tcltls. But this package has a number of disadvantages:

  • it uses OpenSSL/LibreSSL libraries. These libraries are huge (see issue#11308), contain a lot of obsolete and practically useless code/functions
  • no support for CA certificates provided by the operating system
  • unsafe default parameters

There are also alternatives, but they have their disadvantages:

  • Package twapi: Windows platform only; comes as part of the entire twapi package (which is very cool, but also critically huge)
  • Package TclCurl: depends on the even larger cURL library and therefore has both greater build complexity and size; support for client connections only

::mtls solves these disadvantages. It has the following features:

  • uses the mbedTLS library with minimal size
  • interface is compatible with tcltls, most of the existing code will work as is, without modifications
  • uses CA certificates from the operating system on Linux/Windows/MacOS platforms
  • uses only modern TLS1.2/TLS1.3 protocols, which are more than sufficient for successful connections to most services
  • certificate and hostname verification, SNI are enabled by default
  • multi-platform, Linux/Windows/MacOS supported
  • possibility to exclude the client or server part to minimize the size even more
  • easy to build, no 3rd-party libraries, everything you need to build is in this repository
  • was created as a base for the use of SSL/TLS alternative backends

Compatibility

This package requires Tcl 8.6 or later. However it has been tested with Tcl 8.6.14 and 9.0b2.

How to build

This package uses the Tcl Extension Architecture (TEA) to build and install on Linux, Mac, or Windows platforms. For Windows platform only building with Mingw-w64 toolchain is supported.

The standard TEA config, make and install process is supported.

$ git clone https://github.com/chpock/tclmtls.git
$ cd tclmtls
$ git submodule update --init --recursive
$ mkdir build && cd build
$ ../configure
$ make
$ make test
$ make install

The supported configure options include all of the standard TEA configure script options, plus:

--disable-client disable SSL client part
--disable-server disable SSL server part

By default, mbedTLS will be built and used. It is possible to use an already built library, for this it is possible to specify the following options:

--with-mbedtls=<dir> path to root directory of Mbed-TLS installation
--with-mbedtls-include=<dir> path to include directory of Mbed-TLS installation
--with-mbedtls-lib=<dir> path to lib directory of Mbed-TLS installation

Options that can be used for development:

--enable-debug=<level> enable debug messages. Possible levels are: none, error, warning, info or on

Usage

Since this package intends to be compatible with the original tcltls package, the usual tcltls examples should be correct. You can see these examples on the Tcl wiki: https://wiki.tcl-lang.org/page/tls

Minimal examples are available below under HTTPS examples.

Built packages and sources

The source code is available on Github.

Built packages are available on the above Github page, under Releases.

There are packages for the following platforms:

  • Windows x86 and x86_64: Windows XP or higher is required. However, they are only tested on Windows 10.
  • Linux x86 and x86_64: built and tested on Cenos6.10. Require glibc v2.12 or higher.
  • MacOS x86 and x86_64: built and tested on MacOS 10.12. However, these packages should be compatible with MacOS as of version 10.6.

Copyrights

Copyright (C) 2024 Konstantin Kushnir chpock@gmail.com

License

This code is licensed under the same terms as the Tcl Core.

This package contains mbedTLS sources which are distributed under a dual Apache-2.0 OR GPL-2.0-or-later license.

::mtls

Description

This Tcl package provides an extension which implements Transport Layer Security (TLS) over Transmission Control Protocol (TCP) network communication channels.

Typically one would use the socket command which provides compatibility with the native Tcl socket command. In such cases import should not be used directly.

Please note, to ensure seamless use of both the classic tcltls package and this package, command aliases are created in the ::tls namespace when loading mtls. This allows the same code base to be used when using different packages to support SSL/TLS connections. However, aliases will not be created if the ::tls namespace already exists at the time the mtls package is loaded. This in turn allows both the tcltls and mtls packages to be loaded at the same time. But the tcltls package must be loaded first.

HTTPS examples

client example

package require http
package require mtls

http::register https 443 ::mtls::socket

set tok [http::geturl https://www.tcl.tk/]

server example

package require mtls

proc readable { sock } {
    # do something
}

proc accept { sock addr port } {
    fileevent $sock readable [list readable $sock]
}

mtls::socket -certfile $serverCert -keyfile $serverKey -server accept 8080

Commands

ciphers [::mtls]

Gets a list of supported ciphers.

ciphers protocol

Parameters
protocol protocol for which a list of ciphers will be returned. Must be one of tls1.2 or tls1.3.
Description

For compatibility with tcltls, this procedure can also accept verbose and supported arguments. However, they do not affect the result and will be ignored.

Return value

A Tcl list of supported ciphers based on the specified protocol.

debug [::mtls]

Sets the level for debug messages

debug ?integer?
debug ?level? ?backend_level?

Parameters
backend_level sets the desired level for TLS backend debug messages. The format is the same as for the level argument.
integer integer in this form will represent the debugging level for the packet and TLS backend messages. The first 3 bits refer to the packet layer and the next 3 bits refer to the TLS backend layer. The minimum level is 0, which means no messages, and the maximum level is 5, which corresponds to the trace level.
level sets the desired level for package debug messages, which must be one of none, error, warning, info, debug, trace or a number from 0 to 5.
Description

If no arguments are specified, this command simply returns the current level.

Debug messages will only work if the package was built with debugging support. Otherwise, this level will be ignored.

Return value

An unsigned integer corresponding to the current level for both package and TLS backend debug messages.

handshake [::mtls]

Forces handshake to take place

handshake channel

Parameters
channel TLS channel on which the handshake process should be started.
Return value

0 if handshake is still in progress (non-blocking), or 1 if the handshake was successful. If the handshake failed this procedure will throw an error.

import [::mtls]

Adds TLS layer for existing socket channel.

import channel ?options?

Parameters
channel A regular Tcl channel created wich Tcl socket command.
-cadir dir Provide the directory containing the CA certificates.
-cafile filename Provide the CA file.
-cert data Provide the contents of a certificate to use, as a PEM encoded or a binary DER encoded value (X.509 DER).
-certfile filename Provide the name of a file containing certificate to use.
-cipher list Provide the list of cipher suites to use.
-dhparams filename Provide a Diffie-Hellman parameters file.
-key data Provide the private key to use as a PEM encoded or a binary DER encoded value (X.509 DER).
-keyfile filename Provide the private key file. (default: value of -certfile)
-model channel This will force this channel to share the same parameters as the specified channel.
-password callback If supplied, this callback will be invoked to unlock the private key of a certificate. The callback should return a string which represents the password to be used.
-require bool Require a valid certificate from peer during TLS handshake. (default: true for client connections and false for server connections)
-server bool Handshake as server if true, else handshake as client. (default: false)
-servername host Use to name the logical host we are talking to and expecting a certificate for.
-tls1.2 bool Enable use of TLS v1.2 protocol (default: true)
-tls1.3 bool Enable use of TLS v1.3 protocol (default: true)
Description

TLS-enables a regular Tcl channel and sets session parameters for TLS handshake.

For compatibility with tcltls, this procedure can also accept -command callback, -request bool, -ssl2 bool, -ssl3 bool, -tls1 bool and -tls1.1 bool arguments. However, they will be ignored.

Return value

The name of a TLS-enabled Tcl channel that can be used to send and receive data.

init [::mtls]

Sets the default settings for newly created TLS channels.

init ?options?

Parameters
?options? options supported by the import and socket commands.
Description

Sets the default settings for newly created TLS channels. The -model, -server, -servername options will be accepted but silently ignored.

Return value

The dict value with the currently defined default options.

protocols [::mtls]

Get a list of supported TLS protocols.

protocols ``

Return value

A Tcl list of supported TLS protocols.

socket [::mtls]

Create a TLS socket channel.

socket ?options? host port
socket ?-server command? ?options? port

Parameters
-autoservername bool Automatically set the -servername as the host argument (default: true)
options options accepted by the normal Tcl command socket and the import command.
Description

This is a helper function for creating TLS-enabled channels. It behaves exactly the same as the native Tcl socket command, and accepts all of its options. In addition, it takes all parameters from the import command to configure the newly created channel.

It also accepts the option -autoservername. If set to true, the value of the -servername option will be automatically detected from the specified connection parameters.

Return value

The name of a TLS-enabled Tcl channel that can be used to send and receive data.

status [::mtls]

Gets the current security status of an TLS channel.

status channel

Parameters
channel TLS channel from which to obtain status
Description

The returned value will be a Tcl dictionary with the following keys:

version The protocol version used for the connection: TLSv1.1, TLSv1.2, unknown.
cipher The current cipher in use between the client and server.
sbits The number of bits used for the session key.

For compatibility with tcltls, this procedure can also accept -local optional argument. However, it will be ignored.

Return value

The Tcl dict value with the current security status of the TLS channel.

unimport [::mtls]

Unstacks the TLS-enabling of a regular Tcl channel.

unimport channel

Parameters
channel TLS channel from which TLS layer is to be removed.
Description

Provided for symmetry to import command. This unstacks the TLS-enabling of a regular Tcl channel.

Return value

nothing.

version [::mtls]

Get the type and version of the TLS backend in use.

version ``

Return value

A string with the type and version number of the TLS backend used.