Skip to content

bcoin-org/libtorsion

Repository files navigation

libtorsion

cmake

Crypto library in C, primarily for EC. Still semi-experimental.

Used as the backend for bcrypto.

Design Approach

  • Generic, without sacrificing speed or security.
  • Use field element backends generated by fiat-crypto (which have proofs of correctness, formal verification, etc).
  • Use a generic barrett reduction for scalar arithmetic (we use a reimplementation of GMP's mpn_ functions for this).
  • Keep constant-time multiplication algorithms as simple as possible.
  • Constant time, stack-based, and so on.
  • Expose a simple opaque API which accepts all arguments in wire format (this eases implementation for language bindings, wasm, and other ffis).

Current Features

  • Curve Support:

    • p192
    • p224
    • p256
    • p384
    • p521
    • secp256k1
    • curve25519
    • curve448
    • edwards25519
    • edwards448
    • curve1174
  • Schemes:

Example

#include <assert.h>
#include <stddef.h>
#include <torsion/ecc.h>
#include <torsion/hash.h>
#include <torsion/rand.h>

int main(void) {
  wei_curve_t *ec = wei_curve_create(WEI_CURVE_SECP256K1);
  const char str[] = "hello world";
  unsigned char priv[32];
  unsigned char entropy[32];
  unsigned char msg[32];
  unsigned char pub[33];
  unsigned char sig[64];
  sha256_t hash;

  /* Hash our message with sha256. */
  sha256_init(&hash);
  sha256_update(&hash, str, sizeof(str) - 1);
  sha256_final(&hash, msg);

  /* Grab some entropy from the OS. */
  assert(torsion_getentropy(entropy, 32));

  /* Generate a key pair using entropy. */
  ecdsa_privkey_generate(ec, priv, entropy);
  assert(ecdsa_pubkey_create(ec, pub, NULL, priv, 1));

  /* Sign in constant time. */
  assert(ecdsa_sign(ec, sig, NULL, msg, sizeof(msg), priv));

  /* Verify our signature. */
  assert(ecdsa_verify(ec, msg, sizeof(msg), sig, pub, sizeof(pub)));

  /* Cleanup. */
  wei_curve_destroy(ec);

  return 0;
}

Compile with:

$ cc -o example -I/path/to/libtorsion/include example.c /path/to/libtorsion.a

Building

libtorsion supports a CMake build (recommended) and an autotools build.

The CMake build is fairly straightforward and offers the following options:

  • TORSION_ENABLE_ASM=ON - Use inline assembly if available
  • TORSION_ENABLE_COVERAGE=OFF - Enable coverage
  • TORSION_ENABLE_DEBUG=ON - Enable debug build (forces -g or /Zi)
  • TORSION_ENABLE_INT128=ON - Use __int128 if available
  • TORSION_ENABLE_MPI=OFF Export MPI functions
  • TORSION_ENABLE_PIC=ON - Enable PIC
  • TORSION_ENABLE_PTHREAD=ON - Use pthread if present in libc
  • TORSION_ENABLE_RNG=ON - Enable RNG
  • TORSION_ENABLE_SHARED=ON - Build shared library
  • TORSION_ENABLE_TESTS=ON - Build tests
  • TORSION_ENABLE_TLS=ON - Use thread-local storage if available
  • TORSION_ENABLE_VERIFY=OFF - Enable scalar bounds checks

To view the autoconf options, see ./configure --help.

Unix

CMake:

$ cmake -G 'Unix Makefiles' -DCMAKE_BUILD_TYPE=Release .
$ make

Autotools:

./autogen.sh
./configure CFLAGS=-O3
make

Windows

Builds on windows will produce both a static and shared library. To deal with the naming collision, the static library is called libtorsion.lib whereas the shared import library is named torsion.lib (this follows Microsoft's new naming convention).

MSVC:

$ cmake .
$ cmake --build . --config Release

Clang (better performance):

$ cmake -G 'NMake Makefiles' -DCMAKE_C_COMPILER=clang-cl \
                             -DCMAKE_BUILD_TYPE=Release .
$ nmake

For systems without CMake installed, a simple NMake build is also included. It assumes MSVC (cl), but also works with Windows Clang (clang-cl).

$ nmake /F Makefile.msvc
$ nmake /F Makefile.msvc CC=clang-cl

MinGW

Another way to build for Windows is by cross-compiling with MinGW (useful for those averse to Windows or who do not have a Windows machine to build on).

CMake:

$ ./scripts/mingw-cmake cmake -DCMAKE_BUILD_TYPE=Release .
$ make

Autotools:

./autogen.sh
./scripts/mingw-configure ./configure CFLAGS=-O3
make

WASI

CMake:

$ ./scripts/wasi-cmake cmake -DCMAKE_BUILD_TYPE=Release .
$ make

Autotools:

./autogen.sh
./scripts/wasi-configure ./configure CFLAGS=-O3
make

Emscripten

CMake:

$ emcmake cmake -DCMAKE_BUILD_TYPE=Release .
$ make

Autotools:

./autogen.sh
emconfigure ./configure CFLAGS=-O3
make

CMake Subprojects

When CMakeLists.txt is invoked as a CMake subproject, it will expose a single static library target named torsion, skipping all other targets (tests, benchmarks, etc). The static library is built with -fPIC and all symbols hidden, thus allowing other libraries to be built on top of a vendored libtorsion.

Example:

add_subdirectory(deps/libtorsion)
target_link_libraries(my_project PRIVATE torsion)

Alternate Build Systems

libtorsion was written generically enough to support any build system you might want to use, with only a few key configuration options necessary.

Configuration

To incorporate libtorsion into a different build system you must be aware of various configuration options that torsion uses internally.

Any of the following may be passed as defines to the preprocessor:

  • TORSION_EXPORT - Export symbols (necessary for shared if -fvisibility=hidden is passed).
  • TORSION_HAVE_CONFIG - Disables preprocessor-based autoconfiguration¹.
  • TORSION_HAVE_ASM - GNU-flavored inline assembly is available².
  • TORSION_HAVE_INT128 - The __int128 type is available².
  • TORSION_HAVE_PTHREAD - The pthread API is available².
  • TORSION_TLS=[tls-keyword] - Thread-local storage is available².
  • TORSION_COVERAGE - Coverage is enabled via gcov. Disable assertions.
  • TORSION_DEBUG - Enable assertions.
  • TORSION_VERIFY - Enable extra debugging checks.
  • TORSION_HAVE_CLOCK_GETTIME - clock_gettime(3) is available²³.
  • TORSION_HAVE_FORK - fork(2) and waitpid(2) are available²³.
  • TORSION_HAVE_GETTIMEOFDAY - gettimeofday(3) is available²³.
  • TORSION_HAVE_MPI - Export MPI functions.
  • TORSION_HAVE_RNG - libtorsion was compiled with RNG support³.
  • TORSION_HAVE_TIME - time(2) is available²³.
  • TORSION_HAVE_ZLIB - <zlib.h> is available and we are linked with -lz³.

Footnotes:

  1. By default torsion will attempt to autoconfigure some options by using the C preprocessor to detect features.
  2. TORSION_HAVE_CONFIG must be defined for this option to have any effect.
  3. This option affects tests and benchmarks only.

If you are using a build system where detecting features is difficult, you can have libtorsion attempt to auto-detect features using the C preprocessor: simply do not pass -DTORSION_HAVE_CONFIG.

Notes

libtorsion is written to be compatible with C89/C90 (with one caveat: the system must provide an stdint.h header). This means that passing -std=c89 should be fine unless you are building with RNG support. Various C standard libraries base their default features on the language standard and will not expose certain POSIX APIs (or system-specific APIs) if a strict C version is passed.

This also means you should not pass any feature test macros that may downgrade the features apart from what is necessary for the RNG to function. For example, passing _POSIX_SOURCE or _POSIX_C_SOURCE will probably break the RNG on Linux (assuming glibc is used).

Furthermore, the RNG accesses errno, which means a thread-local errno is desirable. By defalt, certain OSes do not expose a thread-safe errno. This includes Solaris and AIX. Please ensure that your build produces thread-safe code (the flags required for this differ from system to system).

The libtorsion codebase is also valid C++ and can be compiled inside your C++ project without any modifications.

Contribution and License Agreement

If you contribute code to this project, you are implicitly allowing your code to be distributed under the MIT license. You are also implicitly verifying that all code is your original work. </legalese>

License

  • Copyright (c) 2020, Christopher Jeffrey (MIT License).

See LICENSE for more info.

Releases

No releases published

Packages

No packages published

Languages