Home

Awesome

SPARKNaCl

SPARK 2014 re-implementation of the TweetNaCl crypto library.

Copyright (c) 2020,2021 Protean Code Limited.

Licence: this work is released under the "New" or "Revised" 3-clause BSD licence. See here for details.

This library is a compact reference implementation of the NaCl crypto library. It was originally inspired by the TweetNaCl implementation, but offers a completely automated static proof of type-safety (and some correctness properties), reasonable performance, and (unlike TweetNaCl) is readable owing to the large number of explanatory comments and contracts in the code.

Alire

Contents

Latest news

Why Bother?

Goals

Challenges

Current state of the release

Tools

Reproducing results

Known weaknesses and TBD items

Acknowledgements

Latest news

14th August 2023

As part of his Summer of Code project, Max A. Scheven has contributed an implementation of the Really Fast Syndrome Based hash function RFSB509, in package SPARKNaCl.Hashing.RFSB509. All proofs complete successfully with GNATProve 12.1.1, and Max has also added regression tests that show the new SPARK Code is consistent with the reference C implementation from SUPERCOP. As part of this work, the "tests" subdirectory has been reorganized to separate sources and objects code files into distinct subdirectories.

22nd June 2022

A bunch of updates have been merged to the master branch recently. Specifically:

Work in progress

I also hope to prepare a new release soon using the latest FSF GNAT and GNATprove builds available from Alire. These new builds effectively take over from what would have been the GNAT Community 2022 release.

21st September 2021

Release 3.0.0 of SPARKNaCl is now available from the Alire package manager. This incorporates all recent changes, and is compatible with the 2020 and 2021 releases of GNAT Community or FSF GNAT 11.2.1 or better. This release is also tagged "alire3.0.0" in the GitHub repo here.

25th June 2021

29th May 2021

11th March 2021

4th March 2021

9th February 2021

3rd December 2020

4th September 2020

1st April 2020

Why Bother?

Given that there are several highly-respected implementations of NaCl out there, including the designers' own reference implementation, it is perhaps not entirely obvious that the world needs another one.

I first encountered TweetNaCl with some fascination - a fully-fledged modern crypto library in so little code! That got me wondering if SPARK 2014 could even manage to express such code, and how the SPARK verification tools would cope. TweetNaCl sets some serious challenges (see below), so it started out as a bit of fun to see if any or all of it could be re-implemented in SPARK.

Goals

SPARKNaCl started out with the simple goal of seeing if a re-implementation of TweetNaCl was even possible in SPARK. We have some form in this area, though, having re-implemented Skein in SPARK some time ago, and (more recently) produced a high-assurance implementation of RFC 4108 for a commercial client.

As the project progressed, though, the goals became a little more ambitious:

Challenges

A modern crypto library like TweetNaCl sets some serious challenges for verification tools and languages like SPARK. In particular:

Current state of the release

This release of SPARKNaCl meets most of the goals above. In particular:

Still on the "to be done" list:

Tools

All development work has been done with the Community 2020 and 2021 Editions of GNAT and SPARK, which are freely available. It also works fine with FSF GNAT 11.2.1 or better, which is now available in Alire. Most development work has been done on MacOS, although test results have been successfully reproduced on 64-bit Linux and Windows 10. Performance testing additionally requires the GNAT 32-bit RISC-V cross compiler from the same source.

The GNATStack tool runs on Linux and uses the output of the RISC-V cross compiler to drive its analysis. GNATStack was built from source, but this is not available in the Community release of GNAT. To obtain the GNATStack sources, you will need a GNAT Pro subscription from AdaCore.

Reproducing results

Assuming you have cloned this repository and have the GNAT and SPARK tools installed, then:

Proofs

gnatprove -Psparknacl

To see a summary of the proof results, see the resulting obj/gnatprove/gnatprove.out file.

To see only failed proofs (of which there should be none), do

gnatprove -Psparknacl --report=fail

NOTE: the project file sets a "steps limit" of 14000 for CVC4 and Z3, and no timeout or memory limit on the provers. THis should give the same results on all machines.

Tests

The test cases from NaCl (from the "tests" directory in the NaCl distribution) have been re-implemented in Ada in the "tests" subdirectory here. A top-level driver program testall.adb runs them all.

Expected results are in expected_test_results the same directory.

A simple Makefile is also supplied that builds and runs two variants of testall.adb and compares the results:

To reproduce:

cd tests
make

should suffice.

A second directory "stress" also contains additional boundary-value and stress-test cases for some of the NaCl functions. A single project file there stressall.gpr builds the test driver program - for example:

cd stress
gprbuild -Pstressall
./stressall

Known weaknesses and TBD items

At this time, there are several items to-be-done:

Acknowledgements

Many thanks to:

  1. Yannick Moy and Claire Dross of AdaCore who helped with SPARK language and toolset issues.
  2. Benoit Viguier, who kindly offered advice and help with explaining the GF "Carry" operation.
  3. Jason Donenfeld for providing pointers to his revised "Carry" algorithm that is used in WireGuard.