A portable implementation of RFC 8439. RFC 8439 deprecated RFC 7539: it contained a few clarifications and also enforced the layout of the cipher stream (to append the tag to the end instead of two separate fields)
ChaCha20-Poly1305 is a modern cryptographic construction to encrypt messages once you have a shared (or session) key. ChaCha20 is a stream cipher and Poly1305 provides authentication. The ChaCha20-Poly1305 construction described in RFC 8349 add associated data to the mix, to help protocol designers merge in some extra state to avoid replay attacks.
I made this library since no other C library offered the following characteristics:
Especially the first 3 points were hard to find together. Most libraries either supported big-endianness but were slower (depending on the compiler) even on little-endian machines. Similarly other libraries would assume you could cast a u8 pointer to u32 pointer without problems (it's both an unaligned read problem and undefined C behavior). The closest one was insane codings' simple c99 implementation. Except that it still had the old style 64bit nonce & 64bit counter and it required a modern compiler to make it fast on little-endian.
The design of the API is quite straight forward, there is no incremental/streaming support since that makes it much easier to mess up.
portable_chacha20_poly1305_encrypttakes plain text buffer (plus optional additional data) and encrypts it into a cipher text buffer. The pointers should not overlap, and the cipher text should have room for the original plain text size +
portable_chacha20_poly1305_decrypttakes a cipher text (plus additional data) and decrypts it (if the data is not tampered with) into the plain text buffer. The pointers should not overlap, and the plain text buffer should have room for cipher text size -
RFC_8439_TAG_SIZE. The function returns the size written to the plain text buffer, less than zero marks an decryption failure.
Please make sure to study the original RFC how to take care of your additional data, key, and nonce. Rough summary: never use the same pair of key & nonce. Random nonce is fine but you have to make sure it is unique for the key. An incrementing nonce is also fine. If you can pick additional data based on something that chances the semantics of your protocol or something you already know about each other.
Portable 8439 is faster if it knows the platform is little endian and if the biggest integer supported by the compiler is also the fastest.
If you are on a platform that is not included in the
detection, you should supply
-D__HAVE_LITTLE_ENDIAN to your compiler.
If you are on a platform where the biggest math operations of the compiler are not the quickest, try measuring the effect of changing the version of the poly1305 implementation.
-DPOLY1305_8BIT, 8->16 bit multiplies, 32 bit additions
-DPOLY1305_16BIT, 16->32 bit multiples, 32 bit additions
-DPOLY1305_32BIT, 32->64 bit multiplies, 64 bit additions
-DPOLY1305_64BIT, 64->128 bit multiplies, 128 bit additions
(quote from the poly1305-donna readme)
As package management in C is a bit of a mess we amalgamate the source code into a single c and h file. Always download the released versions, they are easy to include in your project and also helps the compiler optimize code.
The code is licensed under CC0 and contains code from floodberry/poly1305-donna which is also under a public domain license.