Home

Awesome

Crypto Ancienne: TLS for the Internet of Old Things

Copyright (C) 2020-3 Cameron Kaiser and Contributors. All rights reserved.

Crypto Ancienne, or Cryanc for short, is a TLS library with an aim for compatibility with pre-C99 C compilers and geriatric architectures. The TLS apocalypse may have knocked these hulking beasts out of the running for awhile, but now it's time for the Great Old Computing Ones to reclaim the Earth. That old server in your closet? It's only been sleeping, and now it's ready to take back the Web on the Web's own terms. 1997 just called and it's ticked.

Cryanc is intended as a client library. Although it can facilitate acting as a server, this is probably more efficiently and safely accomplished with a separate reverse proxy to which the encryption can be offloaded.

The use of this library does not make your application cryptographically secure, and certain systems may entirely lack any technological means to make that possible. Its functionality and security should be regarded as, at best, "good enough to shoot yourself in the foot with."

Before you file an issue

Supported features

In addition, carl, the included curl-like utility and the Cryanc example application, also has:

See the carl manual page in this repo for more (in man and Markdown format).

Not yet supported but coming soon

Don't file issues about these. If you do, they will be closed as "user doesn't read documentation" and offenders will be ravenously eaten.

These are all acknowledged limitations in TLSe and should improve as upstream does (or our time to work on it).

Known differences

Working configurations

These are tested using carl, which is the included example, and should "just work." Most configurations can build simply with gcc -O3 -o carl carl.c. The magic for operating system support is almost all in cryanc.c.

Working contributed configurations

These are attested to be working but are maintained by others. Some "just work" and others have specific support in the code base.

Partially working configurations

These platforms do not "just work." It is possible due to various compiler or OS limitations that they may never work completely.

Not tested or not working but might in the future

Porting it to your favourite geriatric platform

Most other platforms with gcc 2.5 or higher, support for 64-bit ints (usually long long) and stdarg.h should "just work."

If your system lacks stdint.h, you can try using -DNOT_POSIX=1 to use the built-in definitions. You may also need to add -include stdarg.h and other headers. Consider compiling with -DDEBUG if you get crashes so you can see where it dies (it's also a neat way to see TLS under the hood).

A few architectures, especially old RISC, may not like the liberties taken with unaligned pointers and memory access. For these systems try -DNO_FUNNY_ALIGNMENT, which is the default for SPARC, HP PA-RISC, MIPS and SuperH. However, it seems we may not have smoked all of them out (for example, it's not good enough for DEC Alpha on Tru64, the king of alignment-finicky configurations, and we still have to use -misalign with the Compaq C compiler).

Large local stack allocations are occasionally used for buffering efficiency. If your compiler doesn't like this (Metrowerks comes to mind) or you get crashes when carl terminates, try -DBIG_STRING_SIZE=xx, substituting a smaller buffer size like 16384 or 4096.

Once you figure out the secret sauce, we encourage you to put some additional blocks into cryanc.c to get the right header files and compiler flags loaded. PRs accepted for these as long as no presently working configuration is regressed. Similarly, we would love to further expand our compiler support, though we now support quite a few.

Some systems may be too slow for present-day server expectations and thus will appear not to function even if the library otherwise works correctly. In our testing this starts to become a problem for CPUs slower than 40MHz or so, regardless of architecture. Even built with -O3, our little NetBSD Macintosh IIci with a 25MHz 68030 and no L2 card took 22 seconds (give carl the -t option to disable timeouts) for a single short TLS 1.2 transaction to a local test server; a number of Internet hosts we tested it with simply cut the connection instead of waiting. Rude!

Using it in your application

A simple #include "cryanc.c" is sufficient (add both cryanc.c and cryanc.h to your source code). cryanc.h serves to document the more or less public interface and can be used if you turn Cryanc into a library instead of simply merging it into your source.

carl demonstrates the basic notion:

Your application then needs to service reads and writes. The loop at the end of carl is a complete example, using select(3) to determine when data has arrived, and using an additional interior read loop to satisfy some servers that demand the socket be serviced promptly.

As data accumulates from the TLS hello and calls to tls_write, it should check tls_get_write_buffer and send this data down the socket. carl has a helper function called https_send_pending which it calls periodically to do this. Once the context write buffer is serviced, it clears the context buffer with tls_buffer_clear.

Likewise, as data is read from the socket, it is sent to tls_consume_stream. When the secure connection is established, tls_established will become true for the context and you can read data from tls_read.

If a TLS alert occurs, it can be fetched from context->error_code.

Language pedantry note

Here, "crypto" is short for la cryptographie and therefore the use of the feminine singular ancienne, so there.

Licenses and copyrights

Crypto Ancienne is released under the BSD license.

Copyright (C) 2020-3 Cameron Kaiser and Contributors. All rights reserved.

Based on TLSe. Copyright (C) 2016-2023 Eduard Suica. All rights reserved.

Based on Adam Langley's implementation of Curve25519. Copyright (C) 2008 Google, Inc. All rights reserved.

Based on OpenBSD's arc4random (allegedly). Copyright (C) 1996 David Mazieres. All rights reserved.

Based on libtomcrypt by Tom St Denis and contributors. Unlicense.

Based on public domain works by D. J. Bernstein.

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

  1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.

  2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.