add bryan hawkins chacha20 source from
authorLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Thu, 29 Dec 2022 12:53:45 +0000 (12:53 +0000)
committerLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Fri, 2 Jun 2023 18:51:16 +0000 (19:51 +0100)
https://github.com/spcnvdr/xchacha20

crypto/chacha20/LICENSE [new file with mode: 0644]
crypto/chacha20/Makefile [new file with mode: 0644]
crypto/chacha20/NOTICE [new file with mode: 0644]
crypto/chacha20/README.md [new file with mode: 0644]
crypto/chacha20/changelog [new file with mode: 0644]
crypto/chacha20/src/test.c [new file with mode: 0644]
crypto/chacha20/src/xchacha20.c [new file with mode: 0644]
crypto/chacha20/src/xchacha20.h [new file with mode: 0644]

diff --git a/crypto/chacha20/LICENSE b/crypto/chacha20/LICENSE
new file mode 100644 (file)
index 0000000..f27c513
--- /dev/null
@@ -0,0 +1,28 @@
+Copyright 2019 Bryan Hawkins <spcnvdrr@protonmail.com>
+
+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.
+
+3. Neither the name of the copyright holder nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+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.
diff --git a/crypto/chacha20/Makefile b/crypto/chacha20/Makefile
new file mode 100644 (file)
index 0000000..ef18a75
--- /dev/null
@@ -0,0 +1,30 @@
+# A simple Makefile, to build run: make all
+TARGET = test
+
+CC     = gcc
+#compiler flags here
+CFLAGS = -O3 -Wall -Wextra
+
+#linker flags here
+LFLAGS = -Wall
+
+SRCDIR = src
+
+SOURCES        := $(wildcard $(SRCDIR)/*.c)
+INCLUDES       := $(wildcard $(SRCDIR)/*.h))
+OBJECTS        := $(SOURCES:$(SRCDIR)/%.c=$(SRCDIR)/%.o)
+
+.PHONY: all clean remove
+all: ${TARGET}
+
+$(TARGET): $(OBJECTS)
+       @$(CC) -o $@ $(LFLAGS) $(OBJECTS)
+
+$(OBJECTS): $(SRCDIR)/%.o : $(SRCDIR)/%.c
+       @$(CC) $(CFLAGS) -c $< -o $@
+
+clean:
+       @$ rm -f $(OBJECTS)
+
+remove: clean
+       @$ rm -f $(TARGET)
diff --git a/crypto/chacha20/NOTICE b/crypto/chacha20/NOTICE
new file mode 100644 (file)
index 0000000..5c3049b
--- /dev/null
@@ -0,0 +1,33 @@
+This project contains code developed by Daniel J. Bernstein which was
+released into the public domain. This code is based on Bernstein's
+"chacha-merged.c version 20080118". Daniel J. Bernstein's original code
+can be found at the following here: http://cr.yp.to/chacha.html
+
+This project also contains code based on part of the libsodium cryptographic
+library. The xchacha_hchacha and xchacha_set_counter functions were borrowed 
+from libsodium and modified.
+More information about libsodium can be found at the following
+websites:
+https://github.com/jedisct1/libsodium
+https://download.libsodium.org/doc/
+
+The code based on libsodium is used under the following license:
+
+/*
+ * ISC License
+ *
+ * Copyright (c) 2013-2019
+ * Frank Denis <j at pureftpd dot org>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
diff --git a/crypto/chacha20/README.md b/crypto/chacha20/README.md
new file mode 100644 (file)
index 0000000..6c75ea0
--- /dev/null
@@ -0,0 +1,119 @@
+# XChaCha20 - Extended Nonce Version of ChaCha20
+
+XChaCha20 is a stream cipher based on ChaCha20. XChaCha20 uses a 256-bit
+key and a 192-bit nonce. According to an [IETF draft:](https://tools.ietf.org/html/draft-arciszewski-xchacha-02), "The eXtended-nonce ChaCha cipher construction (XChaCha) allows for
+ChaCha-based ciphersuites to accept a 192-bit nonce with similar guarantees
+to the original construction, except with a much lower probability of
+nonce misuse occurring. This enables XChaCha constructions to be stateless,
+while retaining the same security assumptions as ChaCha."
+Also, XChaCha20 does not use any look up tables and is immune to
+timing attacks. This library is based on Daniel J. Bernstein's reference
+implementation of the ChaCha stream cipher.
+
+I decided to make this small C library for XChaCha20 because I could not
+find one. Unlike some other libraries, it only allows using XChaCha20 with
+a 256-bit key and a 192-bit nonce. No other key sizes or nonce sizes are
+allowed. A large benefit of using XChaCha20 over the regular ChaCha20 is that
+the larger nonce (192 bits v.s. 64 bits) allows the use of random nonces and
+is more resistant to nonce misuse.
+
+**More Information**
+
+[IETF XChaCha20 Draft](https://tools.ietf.org/html/draft-arciszewski-xchacha-03)
+
+[Bernstein's ChaCha Web page](http://cr.yp.to/chacha.html)
+
+[Libsodium Documentation](https://libsodium.gitbook.io/doc/advanced/stream_ciphers/xchacha20)
+
+[Crypto++ Documentation](https://www.cryptopp.com/wiki/XChaCha20)
+
+[Wikipedia](https://en.wikipedia.org/wiki/Salsa20)
+
+**WARNING**
+
+I am not a cryptographer so use this library at your own risk.  
+
+
+**Getting Started**
+
+Import the library into your project
+
+```C
+    #include "xchacha20.h"
+```
+
+Create a XChaCha context
+
+```C
+    XChaCha_ctx ctx;
+```
+
+Set up the 256-bit encryption key and the 192-bit nonce to be used.
+
+```C
+    xchacha_keysetup(&ctx, key, nonce);
+```
+
+Optionally, set the counter to a different starting value other than zero.
+
+```C
+    xchacha_set_counter(&ctx, 0x1);
+```
+
+Then use xchacha_encrypt_bytes or xchacha_encrypt_blocks to encrypt data
+
+```C
+    xchacha_encrypt_bytes(&ctx, plaintext, ciphertext, sizeof(plaintext));
+```
+
+
+**Test Vectors**
+
+In the src folder is a program named test.c It calculates and compares
+XChaCha20 test vectors obtained from two different sources. The test vectors
+were borrowed from the IETF draft regarding XChaCha20 and an example from
+Crypto++ wikipedia. It will compare the output of this XChaCha20 library with
+known good test vectors to ensure this library is working correctly.
+
+To make the test program simply run make
+
+    make
+
+Then run the test program
+
+    ./test
+
+The program will produce the following output if successful:
+
+    Cryptographic tests passed
+
+If this library failed to generate the correct ciphertexts, then something
+is wrong with the library and you will see this output:
+
+    Cryptographic tests failed!
+
+
+**To Do**
+
+- [x] Add a program to calculate and compare test vectors
+- [ ] Find and add more test vectors for XChaCha20
+
+
+**Contributing**
+
+Pull requests, new feature suggestions, and bug reports/issues are
+welcome.
+
+
+**Versioning**
+
+This project uses semantic versioning 2.0. Version numbers follow the
+MAJOR.MINOR.PATCH format.
+
+
+**License**
+
+This project is licensed under the 3-Clause BSD License also known as the
+*"New BSD License"* or the *"Modified BSD License"*. A copy of the license
+can be found in the LICENSE file. A copy can also be found at the
+[Open Source Institute](https://opensource.org/licenses/BSD-3-Clause)
diff --git a/crypto/chacha20/changelog b/crypto/chacha20/changelog
new file mode 100644 (file)
index 0000000..0a819b8
--- /dev/null
@@ -0,0 +1,33 @@
+xchacha20 (0.0.5) urgency=low;
+  * Corrected confusing comments in the source code.
+
+  -- Bryan Hawkins <spcnvdrr@protonmail.com> Wed, 17 Jul 2019 06:34:18 -0500
+
+xchacha20 (0.0.4) urgency=low;
+  * Added a new test vector from the latest version of the IETF draft.
+    Found here: https://tools.ietf.org/html/draft-arciszewski-xchacha-03
+  * Updated the README.md file.
+
+  -- Bryan Hawkins <spcnvdrr@protonmail.com> Mon, 17 Jun 2019 12:22:44 -0500
+
+xchacha20 (0.0.3) urgency=low;
+  * Fixed minor typos and errors throughout the project
+  * Corrected inconsistent use of tabs v.s. spaces
+  * Fixed a minor warning issued while compiling the library
+
+  -- Bryan Hawkins <spcnvdrr@protonmail.com> Mon, 03 Jun 2019 11:36:49 -0500
+
+xchacha20 (0.0.2) urgency=low;
+  * Added a program to calculate and compare this library's output with
+    known good test vectors.
+  * Fixed minor errors in the README.md file and xchacha.c
+
+  -- Bryan Hawkins <spcnvdrr@protonmail.com> Fri, 31 May 2019 12:49:28 -0500
+
+xchacha20 (0.0.1) urgency=low;
+  * Initial commit and now managing project with Git.
+
+  -- Bryan Hawkins <spcnvdrr@protonmail.com> Tue, 28 May 2019 18:11:11 -0500
+
+
+use the 'date -R' command to make the date string.
diff --git a/crypto/chacha20/src/test.c b/crypto/chacha20/src/test.c
new file mode 100644 (file)
index 0000000..38a56a5
--- /dev/null
@@ -0,0 +1,348 @@
+/*************************************************************************
+ * This is a simple program to calculate test vectors and compare them   *
+ * to known good values for XChaCha20.
+ *************************************************************************/
+#include <stdio.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include "xchacha20.h"
+
+
+/** Calculate and compare the newest test vectors from the IETF
+ * Draft for XchaCha20. The test vectors were taken from
+ * version 03 of the draft:
+ * https://tools.ietf.org/html/draft-arciszewski-xchacha-03
+ * This version was published on: October 11, 2018 and
+ * expired on: June 21, 2019
+ * The biggest difference between this IETF test vector and the
+ * other one is that this version initializes the XChaCha20 internal
+ * counter to 1 instead of 0.
+ * @returns 0 on success, -1 on failure or error
+ *
+ */
+int check_second_ietf(void){
+       XChaCha_ctx ctx;
+       uint8_t *buffer;
+       uint8_t counter[8] = {0x1};
+
+       /* Test vectors from IETF XChaCha20 draft 03 */
+       uint8_t plaintext[] = {
+                       0x54, 0x68, 0x65, 0x20, 0x64, 0x68, 0x6f, 0x6c,
+                       0x65, 0x20, 0x28, 0x70, 0x72, 0x6f, 0x6e, 0x6f,
+                       0x75, 0x6e, 0x63, 0x65, 0x64, 0x20, 0x22, 0x64,
+                       0x6f, 0x6c, 0x65, 0x22, 0x29, 0x20, 0x69, 0x73,
+                       0x20, 0x61, 0x6c, 0x73, 0x6f, 0x20, 0x6b, 0x6e,
+                       0x6f, 0x77, 0x6e, 0x20, 0x61, 0x73, 0x20, 0x74,
+                       0x68, 0x65, 0x20, 0x41, 0x73, 0x69, 0x61, 0x74,
+                       0x69, 0x63, 0x20, 0x77, 0x69, 0x6c, 0x64, 0x20,
+                       0x64, 0x6f, 0x67, 0x2c, 0x20, 0x72, 0x65, 0x64,
+                       0x20, 0x64, 0x6f, 0x67, 0x2c, 0x20, 0x61, 0x6e,
+                       0x64, 0x20, 0x77, 0x68, 0x69, 0x73, 0x74, 0x6c,
+                       0x69, 0x6e, 0x67, 0x20, 0x64, 0x6f, 0x67, 0x2e,
+                       0x20, 0x49, 0x74, 0x20, 0x69, 0x73, 0x20, 0x61,
+                       0x62, 0x6f, 0x75, 0x74, 0x20, 0x74, 0x68, 0x65,
+                       0x20, 0x73, 0x69, 0x7a, 0x65, 0x20, 0x6f, 0x66,
+                       0x20, 0x61, 0x20, 0x47, 0x65, 0x72, 0x6d, 0x61,
+                       0x6e, 0x20, 0x73, 0x68, 0x65, 0x70, 0x68, 0x65,
+                       0x72, 0x64, 0x20, 0x62, 0x75, 0x74, 0x20, 0x6c,
+                       0x6f, 0x6f, 0x6b, 0x73, 0x20, 0x6d, 0x6f, 0x72,
+                       0x65, 0x20, 0x6c, 0x69, 0x6b, 0x65, 0x20, 0x61,
+                       0x20, 0x6c, 0x6f, 0x6e, 0x67, 0x2d, 0x6c, 0x65,
+                       0x67, 0x67, 0x65, 0x64, 0x20, 0x66, 0x6f, 0x78,
+                       0x2e, 0x20, 0x54, 0x68, 0x69, 0x73, 0x20, 0x68,
+                       0x69, 0x67, 0x68, 0x6c, 0x79, 0x20, 0x65, 0x6c,
+                       0x75, 0x73, 0x69, 0x76, 0x65, 0x20, 0x61, 0x6e,
+                       0x64, 0x20, 0x73, 0x6b, 0x69, 0x6c, 0x6c, 0x65,
+                       0x64, 0x20, 0x6a, 0x75, 0x6d, 0x70, 0x65, 0x72,
+                       0x20, 0x69, 0x73, 0x20, 0x63, 0x6c, 0x61, 0x73,
+                       0x73, 0x69, 0x66, 0x69, 0x65, 0x64, 0x20, 0x77,
+                       0x69, 0x74, 0x68, 0x20, 0x77, 0x6f, 0x6c, 0x76,
+                       0x65, 0x73, 0x2c, 0x20, 0x63, 0x6f, 0x79, 0x6f,
+                       0x74, 0x65, 0x73, 0x2c, 0x20, 0x6a, 0x61, 0x63,
+                       0x6b, 0x61, 0x6c, 0x73, 0x2c, 0x20, 0x61, 0x6e,
+                       0x64, 0x20, 0x66, 0x6f, 0x78, 0x65, 0x73, 0x20,
+                       0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x74,
+                       0x61, 0x78, 0x6f, 0x6e, 0x6f, 0x6d, 0x69, 0x63,
+                       0x20, 0x66, 0x61, 0x6d, 0x69, 0x6c, 0x79, 0x20,
+                       0x43, 0x61, 0x6e, 0x69, 0x64, 0x61, 0x65, 0x2e
+       };
+
+       uint8_t key[] = {
+                       0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
+                       0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
+                       0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
+                       0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f
+       };
+
+       uint8_t iv[] = {
+                       0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
+                       0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
+                       0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x58
+       };
+
+       uint8_t correct_ciphertext[] = {
+                       0x7d, 0x0a, 0x2e, 0x6b, 0x7f, 0x7c, 0x65, 0xa2,
+                       0x36, 0x54, 0x26, 0x30, 0x29, 0x4e, 0x06, 0x3b,
+                       0x7a, 0xb9, 0xb5, 0x55, 0xa5, 0xd5, 0x14, 0x9a,
+                       0xa2, 0x1e, 0x4a, 0xe1, 0xe4, 0xfb, 0xce, 0x87,
+                       0xec, 0xc8, 0xe0, 0x8a, 0x8b, 0x5e, 0x35, 0x0a,
+                       0xbe, 0x62, 0x2b, 0x2f, 0xfa, 0x61, 0x7b, 0x20,
+                       0x2c, 0xfa, 0xd7, 0x20, 0x32, 0xa3, 0x03, 0x7e,
+                       0x76, 0xff, 0xdc, 0xdc, 0x43, 0x76, 0xee, 0x05,
+                       0x3a, 0x19, 0x0d, 0x7e, 0x46, 0xca, 0x1d, 0xe0,
+                       0x41, 0x44, 0x85, 0x03, 0x81, 0xb9, 0xcb, 0x29,
+                       0xf0, 0x51, 0x91, 0x53, 0x86, 0xb8, 0xa7, 0x10,
+                       0xb8, 0xac, 0x4d, 0x02, 0x7b, 0x8b, 0x05, 0x0f,
+                       0x7c, 0xba, 0x58, 0x54, 0xe0, 0x28, 0xd5, 0x64,
+                       0xe4, 0x53, 0xb8, 0xa9, 0x68, 0x82, 0x41, 0x73,
+                       0xfc, 0x16, 0x48, 0x8b, 0x89, 0x70, 0xca, 0xc8,
+                       0x28, 0xf1, 0x1a, 0xe5, 0x3c, 0xab, 0xd2, 0x01,
+                       0x12, 0xf8, 0x71, 0x07, 0xdf, 0x24, 0xee, 0x61,
+                       0x83, 0xd2, 0x27, 0x4f, 0xe4, 0xc8, 0xb1, 0x48,
+                       0x55, 0x34, 0xef, 0x2c, 0x5f, 0xbc, 0x1e, 0xc2,
+                       0x4b, 0xfc, 0x36, 0x63, 0xef, 0xaa, 0x08, 0xbc,
+                       0x04, 0x7d, 0x29, 0xd2, 0x50, 0x43, 0x53, 0x2d,
+                       0xb8, 0x39, 0x1a, 0x8a, 0x3d, 0x77, 0x6b, 0xf4,
+                       0x37, 0x2a, 0x69, 0x55, 0x82, 0x7c, 0xcb, 0x0c,
+                       0xdd, 0x4a, 0xf4, 0x03, 0xa7, 0xce, 0x4c, 0x63,
+                       0xd5, 0x95, 0xc7, 0x5a, 0x43, 0xe0, 0x45, 0xf0,
+                       0xcc, 0xe1, 0xf2, 0x9c, 0x8b, 0x93, 0xbd, 0x65,
+                       0xaf, 0xc5, 0x97, 0x49, 0x22, 0xf2, 0x14, 0xa4,
+                       0x0b, 0x7c, 0x40, 0x2c, 0xdb, 0x91, 0xae, 0x73,
+                       0xc0, 0xb6, 0x36, 0x15, 0xcd, 0xad, 0x04, 0x80,
+                       0x68, 0x0f, 0x16, 0x51, 0x5a, 0x7a, 0xce, 0x9d,
+                       0x39, 0x23, 0x64, 0x64, 0x32, 0x8a, 0x37, 0x74,
+                       0x3f, 0xfc, 0x28, 0xf4, 0xdd, 0xb3, 0x24, 0xf4,
+                       0xd0, 0xf5, 0xbb, 0xdc, 0x27, 0x0c, 0x65, 0xb1,
+                       0x74, 0x9a, 0x6e, 0xff, 0xf1, 0xfb, 0xaa, 0x09,
+                       0x53, 0x61, 0x75, 0xcc, 0xd2, 0x9f, 0xb9, 0xe6,
+                       0x05, 0x7b, 0x30, 0x73, 0x20, 0xd3, 0x16, 0x83,
+                       0x8a, 0x9c, 0x71, 0xf7, 0x0b, 0x5b, 0x59, 0x07,
+                       0xa6, 0x6f, 0x7e, 0xa4, 0x9a, 0xad, 0xc4, 0x09
+       };
+
+       /* Allocate a buffer to hold our calculated ciphertext */
+       if((buffer = malloc(1024 * sizeof(uint8_t))) == NULL){
+               perror("malloc() error");
+               return(-1);
+       }
+
+       xchacha_keysetup(&ctx, key, iv);
+
+       /*This version of the IETF draft initializes their counter to 1
+        * instead of 0 */
+       xchacha_set_counter(&ctx, counter);
+       xchacha_encrypt_bytes(&ctx, plaintext, buffer, 304);
+
+       /* Make sure our ciphertext matches */
+       if(memcmp(buffer, correct_ciphertext, 304) != 0){
+               free(buffer);
+               return(-1);
+       }
+
+       free(buffer);
+
+       return(0);
+}
+
+/** Calculate and compare the test vectors from the IETF
+ * Draft for XchaCha20. The test vectors were taken from
+ * this version of the draft:
+ * https://tools.ietf.org/html/draft-arciszewski-xchacha-02
+ * This version was published on: October 11, 2018 and
+ * expired on: April 14, 2019
+ * @returns 0 on success, -1 on failure or error
+ *
+ */
+int check_ietf(void){
+       XChaCha_ctx ctx;
+       uint8_t *buffer;
+
+       /* Test vectors from IETF XChaCha20 draft */
+       uint8_t plaintext[] = {
+                       0x54, 0x68, 0x65, 0x20, 0x64, 0x68, 0x6f, 0x6c,
+                       0x65, 0x20, 0x28, 0x70, 0x72, 0x6f, 0x6e, 0x6f,
+                       0x75, 0x6e, 0x63, 0x65, 0x64, 0x20, 0x22, 0x64,
+                       0x6f, 0x6c, 0x65, 0x22, 0x29, 0x20, 0x69, 0x73,
+                       0x20, 0x61, 0x6c, 0x73, 0x6f, 0x20, 0x6b, 0x6e,
+                       0x6f, 0x77, 0x6e, 0x20, 0x61, 0x73, 0x20, 0x74,
+                       0x68, 0x65, 0x20, 0x41, 0x73, 0x69, 0x61, 0x74,
+                       0x69, 0x63, 0x20, 0x77, 0x69, 0x6c, 0x64, 0x20,
+                       0x64, 0x6f, 0x67, 0x2c, 0x20, 0x72, 0x65, 0x64,
+                       0x20, 0x64, 0x6f, 0x67, 0x2c, 0x20, 0x61, 0x6e,
+                       0x64, 0x20, 0x77, 0x68, 0x69, 0x73, 0x74, 0x6c,
+                       0x69, 0x6e, 0x67, 0x20, 0x64, 0x6f, 0x67, 0x2e,
+                       0x20, 0x49, 0x74, 0x20, 0x69, 0x73, 0x20, 0x61,
+                       0x62, 0x6f, 0x75, 0x74, 0x20, 0x74, 0x68, 0x65,
+                       0x20, 0x73, 0x69, 0x7a, 0x65, 0x20, 0x6f, 0x66,
+                       0x20, 0x61, 0x20, 0x47, 0x65, 0x72, 0x6d, 0x61,
+                       0x6e, 0x20, 0x73, 0x68, 0x65, 0x70, 0x68, 0x65,
+                       0x72, 0x64, 0x20, 0x62, 0x75, 0x74, 0x20, 0x6c,
+                       0x6f, 0x6f, 0x6b, 0x73, 0x20, 0x6d, 0x6f, 0x72,
+                       0x65, 0x20, 0x6c, 0x69, 0x6b, 0x65, 0x20, 0x61,
+                       0x20, 0x6c, 0x6f, 0x6e, 0x67, 0x2d, 0x6c, 0x65,
+                       0x67, 0x67, 0x65, 0x64, 0x20, 0x66, 0x6f, 0x78,
+                       0x2e, 0x20, 0x54, 0x68, 0x69, 0x73, 0x20, 0x68,
+                       0x69, 0x67, 0x68, 0x6c, 0x79, 0x20, 0x65, 0x6c,
+                       0x75, 0x73, 0x69, 0x76, 0x65, 0x20, 0x61, 0x6e,
+                       0x64, 0x20, 0x73, 0x6b, 0x69, 0x6c, 0x6c, 0x65,
+                       0x64, 0x20, 0x6a, 0x75, 0x6d, 0x70, 0x65, 0x72,
+                       0x20, 0x69, 0x73, 0x20, 0x63, 0x6c, 0x61, 0x73,
+                       0x73, 0x69, 0x66, 0x69, 0x65, 0x64, 0x20, 0x77,
+                       0x69, 0x74, 0x68, 0x20, 0x77, 0x6f, 0x6c, 0x76,
+                       0x65, 0x73, 0x2c, 0x20, 0x63, 0x6f, 0x79, 0x6f,
+                       0x74, 0x65, 0x73, 0x2c, 0x20, 0x6a, 0x61, 0x63,
+                       0x6b, 0x61, 0x6c, 0x73, 0x2c, 0x20, 0x61, 0x6e,
+                       0x64, 0x20, 0x66, 0x6f, 0x78, 0x65, 0x73, 0x20,
+                       0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x74,
+                       0x61, 0x78, 0x6f, 0x6e, 0x6f, 0x6d, 0x69, 0x63,
+                       0x20, 0x66, 0x61, 0x6d, 0x69, 0x6c, 0x79, 0x20,
+                       0x43, 0x61, 0x6e, 0x69, 0x64, 0x61, 0x65, 0x2e
+       };
+
+       uint8_t key[] = {
+                       0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
+                       0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
+                       0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
+                       0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f
+       };
+
+       uint8_t iv[] = {
+                       0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
+                       0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
+                       0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x58
+       };
+
+       uint8_t correct_ciphertext[] = {
+                       0x45, 0x59, 0xab, 0xba, 0x4e, 0x48, 0xc1, 0x61,
+                       0x02, 0xe8, 0xbb, 0x2c, 0x05, 0xe6, 0x94, 0x7f,
+                       0x50, 0xa7, 0x86, 0xde, 0x16, 0x2f, 0x9b, 0x0b,
+                       0x7e, 0x59, 0x2a, 0x9b, 0x53, 0xd0, 0xd4, 0xe9,
+                       0x8d, 0x8d, 0x64, 0x10, 0xd5, 0x40, 0xa1, 0xa6,
+                       0x37, 0x5b, 0x26, 0xd8, 0x0d, 0xac, 0xe4, 0xfa,
+                       0xb5, 0x23, 0x84, 0xc7, 0x31, 0xac, 0xbf, 0x16,
+                       0xa5, 0x92, 0x3c, 0x0c, 0x48, 0xd3, 0x57, 0x5d,
+                       0x4d, 0x0d, 0x2c, 0x67, 0x3b, 0x66, 0x6f, 0xaa,
+                       0x73, 0x10, 0x61, 0x27, 0x77, 0x01, 0x09, 0x3a,
+                       0x6b, 0xf7, 0xa1, 0x58, 0xa8, 0x86, 0x42, 0x92,
+                       0xa4, 0x1c, 0x48, 0xe3, 0xa9, 0xb4, 0xc0, 0xda,
+                       0xec, 0xe0, 0xf8, 0xd9, 0x8d, 0x0d, 0x7e, 0x05,
+                       0xb3, 0x7a, 0x30, 0x7b, 0xbb, 0x66, 0x33, 0x31,
+                       0x64, 0xec, 0x9e, 0x1b, 0x24, 0xea, 0x0d, 0x6c,
+                       0x3f, 0xfd, 0xdc, 0xec, 0x4f, 0x68, 0xe7, 0x44,
+                       0x30, 0x56, 0x19, 0x3a, 0x03, 0xc8, 0x10, 0xe1,
+                       0x13, 0x44, 0xca, 0x06, 0xd8, 0xed, 0x8a, 0x2b,
+                       0xfb, 0x1e, 0x8d, 0x48, 0xcf, 0xa6, 0xbc, 0x0e,
+                       0xb4, 0xe2, 0x46, 0x4b, 0x74, 0x81, 0x42, 0x40,
+                       0x7c, 0x9f, 0x43, 0x1a, 0xee, 0x76, 0x99, 0x60,
+                       0xe1, 0x5b, 0xa8, 0xb9, 0x68, 0x90, 0x46, 0x6e,
+                       0xf2, 0x45, 0x75, 0x99, 0x85, 0x23, 0x85, 0xc6,
+                       0x61, 0xf7, 0x52, 0xce, 0x20, 0xf9, 0xda, 0x0c,
+                       0x09, 0xab, 0x6b, 0x19, 0xdf, 0x74, 0xe7, 0x6a,
+                       0x95, 0x96, 0x74, 0x46, 0xf8, 0xd0, 0xfd, 0x41,
+                       0x5e, 0x7b, 0xee, 0x2a, 0x12, 0xa1, 0x14, 0xc2,
+                       0x0e, 0xb5, 0x29, 0x2a, 0xe7, 0xa3, 0x49, 0xae,
+                       0x57, 0x78, 0x20, 0xd5, 0x52, 0x0a, 0x1f, 0x3f,
+                       0xb6, 0x2a, 0x17, 0xce, 0x6a, 0x7e, 0x68, 0xfa,
+                       0x7c, 0x79, 0x11, 0x1d, 0x88, 0x60, 0x92, 0x0b,
+                       0xc0, 0x48, 0xef, 0x43, 0xfe, 0x84, 0x48, 0x6c,
+                       0xcb, 0x87, 0xc2, 0x5f, 0x0a, 0xe0, 0x45, 0xf0,
+                       0xcc, 0xe1, 0xe7, 0x98, 0x9a, 0x9a, 0xa2, 0x20,
+                       0xa2, 0x8b, 0xdd, 0x48, 0x27, 0xe7, 0x51, 0xa2,
+                       0x4a, 0x6d, 0x5c, 0x62, 0xd7, 0x90, 0xa6, 0x63,
+                       0x93, 0xb9, 0x31, 0x11, 0xc1, 0xa5, 0x5d, 0xd7,
+                       0x42, 0x1a, 0x10, 0x18, 0x49, 0x74, 0xc7, 0xc5
+       };
+
+       /* Allocate a buffer to hold our calculated ciphertext */
+       if((buffer = malloc(1024 * sizeof(uint8_t))) == NULL){
+               perror("malloc() error");
+               return(-1);
+       }
+
+       xchacha_keysetup(&ctx, key, iv);
+       xchacha_encrypt_bytes(&ctx, plaintext, buffer, 304);
+
+       /* Make sure our ciphertext matches */
+       if(memcmp(buffer, correct_ciphertext, 304) != 0){
+               free(buffer);
+               return(-1);
+       }
+
+       free(buffer);
+
+       return(0);
+}
+
+
+/** Compare our output to the output of a known good XChaCha20 library.
+ * The test vectors used here are from examples given of the Crypto++
+ * cryptographic library's XChaCha20 examples. These values can be
+ * found here:
+ * https://www.cryptopp.com/wiki/XChaCha20
+ * @returns 0 on success, -1 on failure or error
+ *
+ */
+int check_cpp(void){
+       XChaCha_ctx ctx;
+       uint8_t *buffer;
+       uint8_t counter[8] = {0x1};
+
+       /* Test values from Crypto++ documentation */
+       uint8_t key[] = {
+                       0x5E, 0xC5, 0x8B, 0x6D, 0x51, 0x4F, 0xE0, 0xA5,
+                       0x6F, 0x1E, 0x0D, 0xEA, 0x7B, 0xDC, 0x09, 0x5A,
+                       0x10, 0xF5, 0xB6, 0x18, 0xBD, 0xB6, 0xF2, 0x26,
+                       0x2F, 0xCC, 0x59, 0x7B, 0xB2, 0x30, 0xB3, 0xEF
+       };
+
+       uint8_t iv[] = {
+                       0xA3, 0x45, 0xF5, 0xCF, 0x80, 0x23, 0x51, 0x7C,
+                       0xC0, 0xFC, 0xF0, 0x75, 0x74, 0x8C, 0x86, 0x5F,
+                       0x7D, 0xE8, 0xCA, 0x0C, 0x72, 0x36, 0xAB, 0xDA
+       };
+
+       uint8_t correct_ciphertext[] = {
+                       0xEE, 0xA7, 0xC2, 0x71, 0x19, 0x10, 0x65, 0x69,
+                       0x92, 0xE1, 0xCE, 0xD8, 0x16, 0xE2, 0x0E, 0x62,
+                       0x1B, 0x25, 0x17, 0x82, 0x36, 0x71, 0x6A, 0xE4,
+                       0x99, 0xF2, 0x97, 0x37, 0xA7, 0x2A, 0xFC, 0xF8,
+                       0x6C, 0x72
+       };
+
+       uint8_t plaintext[] = "My Plaintext!! My Dear plaintext!!";
+       uint32_t msglen = strlen((char *)plaintext);
+
+       /* Allocate a buffer to hold our calculated ciphertext */
+       if((buffer = malloc(50 * sizeof(uint8_t))) == NULL){
+               perror("malloc() error");
+               return(-1);
+       }
+
+       xchacha_keysetup(&ctx, key, iv);
+
+       /* Crypto++ initializes their counter to 1 instead of 0 */
+       xchacha_set_counter(&ctx, counter);
+       xchacha_encrypt_bytes(&ctx, plaintext, buffer, msglen);
+
+       /* Compare our ciphertext to the correct ciphertext */
+       if(memcmp(buffer, correct_ciphertext, msglen) != 0){
+               free(buffer);
+               return(-1);
+       }
+
+       free(buffer);
+       return(0);
+}
+
+int main(void){
+       if((check_ietf()) == 0 && (check_cpp()) == 0 && (check_second_ietf() == 0)){
+               printf("Cryptographic tests passed\n");
+       } else {
+               printf("Cryptographic tests failed!\n");
+       }
+
+       return(0);
+}
diff --git a/crypto/chacha20/src/xchacha20.c b/crypto/chacha20/src/xchacha20.c
new file mode 100644 (file)
index 0000000..2b29f60
--- /dev/null
@@ -0,0 +1,289 @@
+/*************************************************************************
+ * This is a small cryptographic library that implements the XChaCha20   *
+ * stream cipher. It is based on "chacha-merged.c version 20080118"      *
+ * created by D. J. Bernstein and released in to the Public domain.      *
+ * Check out his website at: http://cr.yp.to/chacha.html                 *
+ * The xchacha_hchacha() and xchacha_set_counter() functions are based   *
+ * on code found in libsodium. To find the associated license and more   *
+ * info., look in the NOTICE file.                                       *
+ *************************************************************************/
+#include <stdlib.h>
+#include <stdint.h>
+#include "xchacha20.h"
+
+
+/** hchacha an intermediary step towards XChaCha20 based on the
+ * construction and security proof used to create XSalsa20.
+ * @param out Holds output of hchacha
+ * @param in The input to process with hchacha
+ * @param k The key to use with hchacha
+ *
+ */
+void xchacha_hchacha20(uint8_t *out, const uint8_t *in, const uint8_t *k){
+       int i;
+       uint32_t x0, x1, x2, x3, x4, x5, x6, x7;
+       uint32_t x8, x9, x10, x11, x12, x13, x14, x15;
+
+       /* XChaCha Constant */
+       x0 = 0x61707865;
+       x1 = 0x3320646e;
+       x2 = 0x79622d32;
+       x3 = 0x6b206574;
+
+       x4  = U8TO32_LITTLE(k +  0);
+       x5  = U8TO32_LITTLE(k +  4);
+       x6  = U8TO32_LITTLE(k +  8);
+       x7  = U8TO32_LITTLE(k + 12);
+       x8  = U8TO32_LITTLE(k + 16);
+       x9  = U8TO32_LITTLE(k + 20);
+       x10 = U8TO32_LITTLE(k + 24);
+       x11 = U8TO32_LITTLE(k + 28);
+       x12 = U8TO32_LITTLE(in +  0);
+       x13 = U8TO32_LITTLE(in +  4);
+       x14 = U8TO32_LITTLE(in +  8);
+       x15 = U8TO32_LITTLE(in + 12);
+
+       for (i = 0; i < 10; i++){
+               QUARTERROUND(x0, x4,  x8, x12);
+               QUARTERROUND(x1, x5,  x9, x13);
+               QUARTERROUND(x2, x6, x10, x14);
+               QUARTERROUND(x3, x7, x11, x15);
+               QUARTERROUND(x0, x5, x10, x15);
+               QUARTERROUND(x1, x6, x11, x12);
+               QUARTERROUND(x2, x7,  x8, x13);
+               QUARTERROUND(x3, x4,  x9, x14);
+       }
+
+       U32TO8_LITTLE(out +  0, x0);
+       U32TO8_LITTLE(out +  4, x1);
+       U32TO8_LITTLE(out +  8, x2);
+       U32TO8_LITTLE(out + 12, x3);
+       U32TO8_LITTLE(out + 16, x12);
+       U32TO8_LITTLE(out + 20, x13);
+       U32TO8_LITTLE(out + 24, x14);
+       U32TO8_LITTLE(out + 28, x15);
+}
+
+
+/** Setup the XChaCha20 encryption key
+ * @param x The XChaCha20 Context to use
+ * @param k A buffer holding the encryption key to use
+ * @note Valid key sizes are 256 bits, and the only valid IV size
+ * is 192 bits.
+ *
+ */
+void xchacha_keysetup(XChaCha_ctx *ctx, const uint8_t *k, uint8_t *iv){
+       /* The sub-key to use */
+       uint8_t k2[32];
+
+       /* Generate the sub-key to use from the 256-bit key and 192-bit iv
+        * We then use this sub-key and the last 8 bytes of the iv
+        * as normal.
+        */
+       xchacha_hchacha20(k2, iv, k);
+
+
+       ctx->input[0] = 0x61707865;
+       ctx->input[1] = 0x3320646e;
+       ctx->input[2] = 0x79622d32;
+       ctx->input[3] = 0x6b206574;
+       ctx->input[4] = U8TO32_LITTLE(k2 + 0);
+       ctx->input[5] = U8TO32_LITTLE(k2 + 4);
+       ctx->input[6] = U8TO32_LITTLE(k2 + 8);
+       ctx->input[7] = U8TO32_LITTLE(k2 + 12);
+       ctx->input[8] = U8TO32_LITTLE(k2 + 16);
+       ctx->input[9] = U8TO32_LITTLE(k2 + 20);
+       ctx->input[10] = U8TO32_LITTLE(k2 + 24);
+       ctx->input[11] = U8TO32_LITTLE(k2 + 28);
+       ctx->input[12] = 0;                     /* Internal counter */
+       ctx->input[13] = 0;         /* Internal counter */
+       ctx->input[14] = U8TO32_LITTLE(iv + 16);
+       ctx->input[15] = U8TO32_LITTLE(iv + 20);
+}
+
+
+/** Set the internal counter to a specific number. Depending
+ * on the specification, sometimes the counter is started at 1.
+ * @param ctx The XChaCha context to modify
+ * @param counter The number to set the counter to
+ *
+ */
+void xchacha_set_counter(XChaCha_ctx *ctx, uint8_t *counter){
+       ctx->input[12] = U8TO32_LITTLE(counter + 0);
+       ctx->input[13] = U8TO32_LITTLE(counter + 4);
+}
+
+
+/** Encrypt data with the XChaCha20 stream cipher
+ * @param x The XChaCha20 context with the cipher's state to use
+ * @param m The plaintext to encrypt
+ * @param c A buffer to hold the ciphertext created from the plaintext
+ * @param bytes The length of the plaintext to encrypt
+ * @note length of c must be >= the length of m otherwise a buffer
+ * overflow will occur.
+ *
+ */
+void xchacha_encrypt_bytes(XChaCha_ctx *ctx, const uint8_t *m, uint8_t *c, uint32_t bytes){
+       uint32_t x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15;
+       uint32_t j0, j1, j2, j3, j4, j5, j6, j7, j8, j9, j10, j11, j12, j13, j14, j15;
+       uint8_t *ctarget = NULL;
+       uint8_t tmp[64];
+       uint32_t i;
+
+       if (!bytes) return;
+
+       j0 = ctx->input[0];
+       j1 = ctx->input[1];
+       j2 = ctx->input[2];
+       j3 = ctx->input[3];
+       j4 = ctx->input[4];
+       j5 = ctx->input[5];
+       j6 = ctx->input[6];
+       j7 = ctx->input[7];
+       j8 = ctx->input[8];
+       j9 = ctx->input[9];
+       j10 = ctx->input[10];
+       j11 = ctx->input[11];
+       j12 = ctx->input[12];
+       j13 = ctx->input[13];
+       j14 = ctx->input[14];
+       j15 = ctx->input[15];
+
+       for (;;) {
+                       if (bytes < 64) {
+                               for (i = 0;i < bytes;++i)
+                                       tmp[i] = m[i];
+                               m = tmp;
+                               ctarget = c;
+                               c = tmp;
+                       }
+               x0 = j0;
+               x1 = j1;
+               x2 = j2;
+               x3 = j3;
+               x4 = j4;
+               x5 = j5;
+               x6 = j6;
+               x7 = j7;
+               x8 = j8;
+               x9 = j9;
+               x10 = j10;
+               x11 = j11;
+               x12 = j12;
+               x13 = j13;
+               x14 = j14;
+               x15 = j15;
+
+               /* Do 20 rounds instead of 8 */
+               for (i = 20;i > 0;i -= 2) {
+                       QUARTERROUND( x0, x4, x8,x12)
+                       QUARTERROUND( x1, x5, x9,x13)
+                       QUARTERROUND( x2, x6,x10,x14)
+                       QUARTERROUND( x3, x7,x11,x15)
+                       QUARTERROUND( x0, x5,x10,x15)
+                       QUARTERROUND( x1, x6,x11,x12)
+                       QUARTERROUND( x2, x7, x8,x13)
+                       QUARTERROUND( x3, x4, x9,x14)
+               }
+               x0 = PLUS(x0,j0);
+               x1 = PLUS(x1,j1);
+               x2 = PLUS(x2,j2);
+               x3 = PLUS(x3,j3);
+               x4 = PLUS(x4,j4);
+               x5 = PLUS(x5,j5);
+               x6 = PLUS(x6,j6);
+               x7 = PLUS(x7,j7);
+               x8 = PLUS(x8,j8);
+               x9 = PLUS(x9,j9);
+               x10 = PLUS(x10,j10);
+               x11 = PLUS(x11,j11);
+               x12 = PLUS(x12,j12);
+               x13 = PLUS(x13,j13);
+               x14 = PLUS(x14,j14);
+               x15 = PLUS(x15,j15);
+
+               x0 = XOR(x0,U8TO32_LITTLE(m + 0));
+               x1 = XOR(x1,U8TO32_LITTLE(m + 4));
+               x2 = XOR(x2,U8TO32_LITTLE(m + 8));
+               x3 = XOR(x3,U8TO32_LITTLE(m + 12));
+               x4 = XOR(x4,U8TO32_LITTLE(m + 16));
+               x5 = XOR(x5,U8TO32_LITTLE(m + 20));
+               x6 = XOR(x6,U8TO32_LITTLE(m + 24));
+               x7 = XOR(x7,U8TO32_LITTLE(m + 28));
+               x8 = XOR(x8,U8TO32_LITTLE(m + 32));
+               x9 = XOR(x9,U8TO32_LITTLE(m + 36));
+               x10 = XOR(x10,U8TO32_LITTLE(m + 40));
+               x11 = XOR(x11,U8TO32_LITTLE(m + 44));
+               x12 = XOR(x12,U8TO32_LITTLE(m + 48));
+               x13 = XOR(x13,U8TO32_LITTLE(m + 52));
+               x14 = XOR(x14,U8TO32_LITTLE(m + 56));
+               x15 = XOR(x15,U8TO32_LITTLE(m + 60));
+
+               j12 = PLUSONE(j12);
+               if (!j12) {
+                       j13 = PLUSONE(j13);
+               }
+
+               U32TO8_LITTLE(c + 0,x0);
+               U32TO8_LITTLE(c + 4,x1);
+               U32TO8_LITTLE(c + 8,x2);
+               U32TO8_LITTLE(c + 12,x3);
+               U32TO8_LITTLE(c + 16,x4);
+               U32TO8_LITTLE(c + 20,x5);
+               U32TO8_LITTLE(c + 24,x6);
+               U32TO8_LITTLE(c + 28,x7);
+               U32TO8_LITTLE(c + 32,x8);
+               U32TO8_LITTLE(c + 36,x9);
+               U32TO8_LITTLE(c + 40,x10);
+               U32TO8_LITTLE(c + 44,x11);
+               U32TO8_LITTLE(c + 48,x12);
+               U32TO8_LITTLE(c + 52,x13);
+               U32TO8_LITTLE(c + 56,x14);
+               U32TO8_LITTLE(c + 60,x15);
+
+               if (bytes <= 64) {
+                       if (bytes < 64) {
+                               for (i = 0;i < bytes;++i)
+                                       ctarget[i] = c[i];
+                       }
+               ctx->input[12] = j12;
+               ctx->input[13] = j13;
+               return;
+               }
+               bytes -= 64;
+               c += 64;
+               m += 64;
+       }
+}
+
+
+/** Decrypt data with the XChaCha20 stream cipher
+ * @param x The XChaCha20 context with the cipher's state to use
+ * @param c The ciphertext to decrypt
+ * @param m A buffer to hold the plaintext
+ * @param bytes The number of bytes of ciphertext to decrypt
+ * @note length of m must be >= the length of c otherwise a buffer
+ * overflow will occur.
+ *
+ */
+void xchacha_decrypt_bytes(XChaCha_ctx *ctx, const uint8_t *c, uint8_t *m, uint32_t bytes){
+       xchacha_encrypt_bytes(ctx,c,m,bytes);
+}
+
+
+/** Generate a keystream from encrypting a zero byte plaintext
+ * @param x The XChaCha context to use
+ * @param stream A buffer to store the generated keystream
+ * @param bytes The number of bytes of keystream to generate
+ * @note Mostly for testing purposes
+ *
+ */
+void xchacha_keystream_bytes(XChaCha_ctx *ctx, uint8_t *stream, uint32_t bytes){
+       uint32_t i;
+
+       for (i = 0;i < bytes;++i){
+               stream[i] = 0;
+       }
+
+       xchacha_encrypt_bytes(ctx,stream,stream,bytes);
+}
diff --git a/crypto/chacha20/src/xchacha20.h b/crypto/chacha20/src/xchacha20.h
new file mode 100644 (file)
index 0000000..84ac3f4
--- /dev/null
@@ -0,0 +1,212 @@
+/*************************************************************************
+ * This is a small library for the XChaCha20 encryption algorithm. This  *
+ * library is based on Daniel J. Bernstein's ChaCha reference            *
+ * implementation, which can be found here: http://cr.yp.to/chacha.html  *
+ * The xchacha_hchacha() and xchacha_set_counter functions are based on  *
+ * code found in libsodium. To find the associated license and more      *
+ * info., look in the NOTICE file.                                       *
+ *************************************************************************/
+#include <stdint.h>
+
+#ifndef XCHACHA20_H_
+#define XCHACHA20_H_
+
+
+/** Key and IV sizes that are supported by XChaCha20.
+ *  All sizes are in bits.
+ */
+#define NAME "XChaCha20"
+#define KEYSIZE 256                 /* 256-bits, 32 bytes */
+#define BLOCKSIZE 512               /* 512-bits, 64 bytes */
+#define IVSIZE 192                  /* 192-bits, 24 bytes */
+
+
+/* XChaCha20 block size in bytes */
+#define XCHACHA_BLOCKLENGTH 64
+
+
+/* The following macros are used to obtain exact-width results. */
+#define U8V(v) ((uint8_t)(v) & (0xFF))
+#define U16V(v) ((uint16_t)(v) & (0xFFFF))
+#define U32V(v) ((uint32_t)(v) & (0xFFFFFFFF))
+#define U64V(v) ((uint64_t)(v) & (0xFFFFFFFFFFFFFFFF))
+
+
+/** The following macros return words with their bits rotated over n
+ *  positions to the left/right.
+ */
+#define ROTL32(v, n) \
+  (U32V((v) << (n)) | ((v) >> (32 - (n))))
+
+
+/** The following macros load words from an array of bytes with
+ *  different types of endianness, and vice versa.
+ */
+#define U8TO32_LITTLE(p) \
+  (((uint32_t)((p)[0])      ) | \
+   ((uint32_t)((p)[1]) <<  8) | \
+   ((uint32_t)((p)[2]) << 16) | \
+   ((uint32_t)((p)[3]) << 24))
+
+#define U32TO8_LITTLE(p, v) \
+  do { \
+    (p)[0] = U8V((v)      ); \
+    (p)[1] = U8V((v) >>  8); \
+    (p)[2] = U8V((v) >> 16); \
+    (p)[3] = U8V((v) >> 24); \
+  } while (0)
+
+
+#define ROTATE(v,c) (ROTL32(v,c))
+#define XOR(v,w) ((v) ^ (w))
+#define PLUS(v,w) (U32V((v) + (w)))
+#define PLUSONE(v) (PLUS((v),1))
+
+
+/* The ChaCha quarter round */
+#define QUARTERROUND(a,b,c,d) \
+  a = PLUS(a,b); d = ROTATE(XOR(d,a),16); \
+  c = PLUS(c,d); b = ROTATE(XOR(b,c),12); \
+  a = PLUS(a,b); d = ROTATE(XOR(d,a), 8); \
+  c = PLUS(c,d); b = ROTATE(XOR(b,c), 7);
+
+
+/** ChaCha_ctx is the structure containing the representation of the
+ *  internal state of the XChaCha20 cipher.
+ *
+ */
+typedef struct
+{
+  uint32_t input[16];
+} XChaCha_ctx;
+
+
+/* ------------------------------------------------------------------------- */
+
+
+/** hchacha an intermediary step towards XChaCha20 based on the
+ * construction and security proof used to create XSalsa20.
+ * @param out Holds output of hchacha
+ * @param in The input to process with hchacha
+ * @param k The key to use with hchacha
+ *
+ */
+void xchacha_hchacha20(uint8_t *out, const uint8_t *in, const uint8_t *k);
+
+
+/** Set the encryption key and iv to be used with XChaCha
+ * @param ctx The XChaCha context to use
+ * @param k The 256-bit/32-byte key to use for encryption
+ * @param iv The 192-bit/24-byte iv or nonce to use
+ * @note It is the user's responsibility to ensure that the key
+ * and the iv are of the correct lengths!
+ */
+void xchacha_keysetup(XChaCha_ctx *ctx, const uint8_t *k, uint8_t *iv);
+
+
+/** Set the internal counter to a specific number. Depending
+ * on the specification, sometimes the counter is started at 1.
+ * @param ctx The XChaCha context to modify
+ * @param counter The number to set the counter to
+ *
+ */
+void xchacha_set_counter(XChaCha_ctx *ctx, uint8_t *counter);
+
+
+/** Encryption/decryption of arbitrary length messages.
+ *
+ *  For efficiency reasons, the API provides two types of
+ *  encrypt/decrypt functions. The xchacha_encrypt_bytes() function
+ *  (declared here) encrypts byte strings of arbitrary length, while
+ *  the xchacha_encrypt_blocks() function (defined later) only accepts
+ *  lengths which are multiples of CHACHA_BLOCKLENGTH.
+ *
+ *  The user is allowed to make multiple calls to
+ *  xchacha_encrypt_blocks() to incrementally encrypt a long message,
+ *  but he is NOT allowed to make additional encryption calls once he
+ *  has called xchacha_encrypt_bytes() (unless he starts a new message
+ *  of course). For example, this sequence of calls is acceptable:
+ *
+ *  xchacha_keysetup();
+ *
+ *  xchacha_ivsetup();
+ *  xchacha_encrypt_blocks();
+ *  xchacha_encrypt_blocks();
+ *  xchacha_encrypt_bytes();
+ *
+ *  xchacha_ivsetup();
+ *  xchacha_encrypt_blocks();
+ *  xchacha_encrypt_blocks();
+ *
+ *  xchacha_ivsetup();
+ *  xchacha_encrypt_bytes();
+ *
+ *  The following sequence is not:
+ *
+ *  xchacha_keysetup();
+ *  xchacha_ivsetup();
+ *  xchacha_encrypt_blocks();
+ *  xchacha_encrypt_bytes();
+ *  xchacha_encrypt_blocks();
+ *
+ */
+
+
+/** Encrypt a set of bytes with XChaCha20
+ * @param ctx The XChaCha20 context to use
+ * @param plaintext The data to be encrypted
+ * @param ciphertext A buffer to hold the encrypted data
+ * @param msglen Message length in bytes
+ *
+ */
+void xchacha_encrypt_bytes(XChaCha_ctx* ctx, const uint8_t* plaintext,
+               uint8_t* ciphertext,
+               uint32_t msglen);
+
+
+/** Dencrypt a set of bytes with XChaCha20
+ * @param ctx The XChaCha20 context to use
+ * @param ciphertext The encrypted data to decrypt
+ * @param plaintext A buffer to hold the decrypted data
+ * @param msglen Message length in bytes
+ *
+ */
+void xchacha_decrypt_bytes(XChaCha_ctx* ctx, const uint8_t* ciphertext,
+               uint8_t* plaintext,
+               uint32_t msglen);
+
+
+/** For testing purposes it can sometimes be useful to have a function
+ *  which immediately generates keystream without having to provide it
+ *  with a zero plaintext.
+ *  @param ctx The XChaCha context to use
+ *  @param keystream A buffer to hold the keystream
+ *  @param length Length of keystream in bytes
+ *
+ */
+void xchacha_keystream_bytes(XChaCha_ctx* ctx, uint8_t* keystream, uint32_t length);
+
+
+/** Encrypt/decrypt of blocks.
+ *  @param ctx The XChaCha context to use
+ *  @param plaintext A buffer which holds unencrypted data
+ *  @param ciphertext A buffer which holds encrypted data
+ *  @param blocks The number of 512 blocks to process with XChaCha20
+ *
+ */
+#define xchacha_encrypt_blocks(ctx, plaintext, ciphertext, blocks)         \
+               xchacha_encrypt_bytes(ctx, plaintext, ciphertext,                        \
+    (blocks) * XCHACHA_BLOCKLENGTH)
+
+
+#define xchacha_decrypt_blocks(ctx, ciphertext, plaintext, blocks)         \
+               xchacha_decrypt_bytes(ctx, ciphertext, plaintext,                      \
+    (blocks) * XCHACHA_BLOCKLENGTH)
+
+
+#define xchacha_keystream_blocks(ctx, keystream, blocks)                   \
+               xchacha_keystream_bytes(ctx, keystream,                                  \
+    (blocks) * XCHACHA_BLOCKLENGTH)
+
+
+#endif