Using the NaCl Crypto Library

This is a technology preview, intended for obtaining feedback from the community. In a first step of this process, we are interested in

  • whether we should submit this library to Microsoft as a new core component of NETMF - i.e., would it be valuable for your projects?
  • whether there are problems with the C# adaptation of the API (API review - see the sections NaCl API and NaCl library extensions below)

If the feedback is sufficiently positive, we will publish the complete source code, so that it can be checked for implementation issues (code review).

We are not interested in algorithm reviews, as this library has already been available for peer reviews within the cryptography community for years by now, and we probably wouldn't be able to seriously assess review comments anyway.

Eventually, we would submit the library as an open source contribution to the NETMF team at Microsoft. Until then, we use the namespace Oberon.NaCl (rather than Mountaineer.NaCl or Microsoft.NaCl), to emphasize the currently still experimental nature of this feature.

For giving feedback, please use this thread on the GHI forum.

Stuxnet, Snowden's revelations about the NSA, SCADA honeypots that have been attacked within hours, or this map of vulnerable industrial equipment have started to make vendors and buyers of embedded systems more aware of the security risks that they face. Most security libraries and protocols require a large memory footprint and a huge number of processor cycles, making them ill suited for microcontroller-based systems. For example, OpenSSL is an order of magnitude too large for Mountaineer mainboards with their 192 KB of RAM and 1 MB of flash memory.

NaCl library

For years we have observed the crypto community's discussions of crypto algorithms, protocols and implementations. We wanted to find a library suitable for single-chip microcontrollers - which are the foundation for the Internet of Things. Finally we have chosen Daniel J. Bernstein's NaCl library (which stands for "networking and cryptography library" and is pronounced as "salt"). This public domain crypto library is well regarded among professional cryptographers (which we are not), is highly efficient, and can be completely implemented in a small footprint. Its goal is to provide "all of the core operations needed to build higher-level cryptographic tools".  It supports both symmetric (private key) as well as asymmetric (public key) encryption.

To make NaCl available to NETMF, we extracted one implementation for each algorithm from Bernstein's C code (he provides several variants for performance optimizations), adapted the NaCl API to C#, and built the necessary interop between C# and NaCl.

Some possible applications of NaCl on a microcontroller system are:

  • Encrypting and signing firmware images, to prevent attackers from tampering or reverse engineering the images while in transit (e.g. online over the Internet, or offline on USB sticks).
  • As a building block for implementing lightweight, end-to-end secure Internet communication protocols.

A great introduction to NaCl on NETMF was written by Marco Poponi here.

NaCl API

Small size and high speed / low power consumption have been the most important reasons for selecting NaCl. Its API is another key reason. Traditional crypto APIs require many steps, and many algorithm and option choices. This makes their use highly error-prone. For example, it was found that almost 90% of all Android apps violate some best practices when using the built-in crypto API (reference). NaCl has a far simpler API, which poses far less risk of using it incorrectly.

When adapting the NaCl API to C#, we started with the following axiom:

 

The design of a security API is a hard problem. It is easy to get it wrong in subtle ways. The larger the gap between the original API and our C# API, the more likely it becomes that client programmers make mistakes when translating between the two. Therefore our goal is to stick as closely as possibly to Bernstein's API, as documented on his Web site (see the links below).

 

As a result, we kept method signatures as similar as possible (names, order of parameters, types, result codes instead of exceptions), with the following exceptions:

  • C pointers are translated to byte arrays plus offsets.
  • C namespace prefixes for functions are replaced by the C# namespace Oberon.NaCl plus class names derived from the C function names. For example, the function crypto_box_open_afternm is translated to method CryptoBox.OpenAfterNm in namespace Oberon.NaCl.
    • According to the .NET library design guidelines, underscores in public identifiers have been eliminated.

    • According to the .NET library design guidelines, identifiers are Pascal-cased (upper camel cased).
  • Unsigned long is replaced by int (32-bit), as NETMF cannot reasonably deal with messages that require 64-bit for representing their lengths, and 64-bit values are expensive for processing.
  • Precondition violations are signaled through .NET argument exceptions. Such exceptions indicate bugs in the client code and should never be caught.

Note that the (constant time) precondition checks make the API completely memory safe: wrong use of the API cannot introduce security holes by allowing to overwrite unrelated memory, nor could it crash the runtime.

NaCl documentation

The authoritative documentation of NaCl is here:

 

Public key crytography (asymmetric keys):

http://nacl.cr.yp.to/box.html

http://nacl.cr.yp.to/scalarmult.html

http://nacl.cr.yp.to/sign.html

 

Private key cryptography (symmetric keys):

http://nacl.cr.yp.to/secretbox.html

http://nacl.cr.yp.to/stream.html

http://nacl.cr.yp.to/auth.html (not supported, as this is redundant functionality)

http://nacl.cr.yp.to/onetimeauth.html

 

Helper functions:

http://nacl.cr.yp.to/hash.html

http://nacl.cr.yp.to/verify.html

NaCl samples

A sample that shows how to encrypt and decrypt a message is given here.

A sample that shows how to sign and verify a message is given here.

NaCl library extensions

The goal for this library is to act as a building block that is as small and as stable as possible, leaving out all redundancies that would cost valuable resources. For example, we on purpose only provide SHA512, leaving out SHA256.

If you have ideas for extending the functionality of NaCl, please add a new, separate API on top of Oberon.NaCl.

NaCl library implementation

Our library wraps the NaCl reference C code as published on http://nacl.cr.yp.to/. The exception is - as recommended - the implementation of the crypto_sign function, which uses the SUPERCOP Ed25519 implementation instead. As this algorithm uses a very large table for multiplication, we replaced the table by a smaller one (tradeoff between speed and code size).