├── .gitignore ├── .travis.yml ├── LICENSE ├── Makefile ├── README.md ├── example └── chacha20_example.c ├── src ├── chacha20.c └── chacha20.h └── test ├── chacha20_test.c └── minunit.h /.gitignore: -------------------------------------------------------------------------------- 1 | # Object files 2 | *.o 3 | *.ko 4 | *.obj 5 | *.elf 6 | 7 | # Precompiled Headers 8 | *.gch 9 | *.pch 10 | 11 | # Libraries 12 | *.lib 13 | *.a 14 | *.la 15 | *.lo 16 | 17 | # Shared objects (inc. Windows DLLs) 18 | *.dll 19 | *.so 20 | *.so.* 21 | *.dylib 22 | 23 | # Executables 24 | *.exe 25 | *.out 26 | *.app 27 | *.i*86 28 | *.x86_64 29 | *.hex 30 | 31 | # Debug files 32 | *.dSYM/ 33 | *.su 34 | 35 | chacha20_test 36 | chacha20_example 37 | libchacha20.so 38 | libchacha20.a 39 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: c 2 | 3 | sudo: false 4 | 5 | compiler: 6 | - clang 7 | - gcc 8 | 9 | script: 10 | - make chacha20_test 11 | - make chacha20_example 12 | - make libchacha20.so 13 | - make libchacha20.a 14 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | OS := $(shell uname) 2 | 3 | CC := gcc 4 | 5 | CFLAGS := -g -Wall -O3 -DLINUX -Isrc 6 | 7 | SOFLAGS := -g -DLINUX -shared -fPIC -Isrc 8 | 9 | LDFLAGS := -Wl,-rpath,bin,-rpath,-lstdc++ 10 | ifneq ($(OS), Darwin) 11 | LDFLAGS := $(LDFLAGS),-lrt 12 | endif 13 | 14 | TARGET = chacha20 15 | 16 | # vpath indicate the searching path of the according file type 17 | vpath %.c src 18 | vpath %.h src 19 | 20 | all: lib$(TARGET).so lib$(TARGET).a $(TARGET)_test $(TARGET)_example 21 | 22 | $(TARGET)_test: test/$(TARGET)_test.c $(TARGET).c 23 | $(CC) test/$(TARGET)_test.c $(CFLAGS) $(LDFLAGS) -o $@ 24 | ./$@ 25 | rm -rf ./$@ 26 | 27 | $(TARGET)_example: example/$(TARGET)_example.c $(TARGET).c 28 | $(CC) $^ $(CFLAGS) $(LDFLAGS) -o $@ 29 | ./$@ 30 | rm -rf ./$@ 31 | 32 | lib%.a: %.c 33 | ar rcs $@ $^ 34 | 35 | lib%.so: %.c 36 | $(CC) $^ $(SOFLAGS) -o $@ 37 | 38 | .PHONY : clean 39 | clean : 40 | rm -rf $(TARGET)_test 41 | rm -rf $(TARGET)_example 42 | rm -rf lib$(TARGET).so 43 | rm -rf lib$(TARGET).a 44 | rm -rf *.dSYM 45 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # chacha20 2 | [![Build Status](https://travis-ci.org/shiffthq/chacha20.svg?branch=master)](https://travis-ci.org/shiffthq/chacha20) 3 | 4 | ChaCha20 stream cipher in C 5 | -------------------------------------------------------------------------------- /example/chacha20_example.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "chacha20.h" 3 | 4 | int main(int argc, char **argv) { 5 | int i; 6 | 7 | uint8_t key[] = { 8 | 0x00, 0x01, 0x02, 0x03, 9 | 0x04, 0x05, 0x06, 0x07, 10 | 0x08, 0x09, 0x0a, 0x0b, 11 | 0x0c, 0x0d, 0x0e, 0x0f, 12 | 0x10, 0x11, 0x12, 0x13, 13 | 0x14, 0x15, 0x16, 0x17, 14 | 0x18, 0x19, 0x1a, 0x1b, 15 | 0x1c, 0x1d, 0x1e, 0x1f 16 | }; 17 | 18 | uint8_t nonce[] = { 19 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4a, 0x00, 0x00, 0x00, 0x00 20 | }; 21 | 22 | uint8_t input[114] = { 23 | 0x4c, 0x61, 0x64, 0x69, 0x65, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x47, 0x65, 0x6e, 0x74, 0x6c, 24 | 0x65, 0x6d, 0x65, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x61, 0x73, 25 | 0x73, 0x20, 0x6f, 0x66, 0x20, 0x27, 0x39, 0x39, 0x3a, 0x20, 0x49, 0x66, 0x20, 0x49, 0x20, 0x63, 26 | 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x6f, 0x66, 0x66, 0x65, 0x72, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x6f, 27 | 0x6e, 0x6c, 0x79, 0x20, 0x6f, 0x6e, 0x65, 0x20, 0x74, 0x69, 0x70, 0x20, 0x66, 0x6f, 0x72, 0x20, 28 | 0x74, 0x68, 0x65, 0x20, 0x66, 0x75, 0x74, 0x75, 0x72, 0x65, 0x2c, 0x20, 0x73, 0x75, 0x6e, 0x73, 29 | 0x63, 0x72, 0x65, 0x65, 0x6e, 0x20, 0x77, 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x62, 0x65, 0x20, 0x69, 30 | 0x74, 0x2e 31 | }; 32 | 33 | uint8_t encrypt[114]; 34 | uint8_t decrypt[114]; 35 | 36 | ChaCha20XOR(key, 1, nonce, input, encrypt, 114); 37 | ChaCha20XOR(key, 1, nonce, encrypt, decrypt, 114); 38 | 39 | printf("\nkey:"); 40 | for (i = 0; i < 32; i++) { 41 | if (!(i % 16)) { 42 | printf("\n"); 43 | } 44 | printf("%02x ", key[i]); 45 | } 46 | 47 | printf("\n\nnonce:\n"); 48 | for (i = 0; i < 12; i++) { 49 | printf("%02x ", nonce[i]); 50 | } 51 | 52 | printf("\n\nplaintext:"); 53 | for (i = 0; i < 114; i++) { 54 | if (!(i % 16)) { 55 | printf("\n"); 56 | } 57 | printf("%02x ", input[i]); 58 | } 59 | 60 | printf("\n\nencrypted:"); 61 | for (i = 0; i < 114; i++) { 62 | if (!(i % 16)) { 63 | printf("\n"); 64 | } 65 | printf("%02x ", encrypt[i]); 66 | } 67 | 68 | printf("\n\ndecrypted:"); 69 | for (i = 0; i < 114; i++) { 70 | if (!(i % 16)) { 71 | printf("\n"); 72 | } 73 | printf("%02x ", decrypt[i]); 74 | } 75 | 76 | printf("\n"); 77 | return 0; 78 | } 79 | -------------------------------------------------------------------------------- /src/chacha20.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "chacha20.h" 4 | 5 | static inline void u32t8le(uint32_t v, uint8_t p[4]) { 6 | p[0] = v & 0xff; 7 | p[1] = (v >> 8) & 0xff; 8 | p[2] = (v >> 16) & 0xff; 9 | p[3] = (v >> 24) & 0xff; 10 | } 11 | 12 | static inline uint32_t u8t32le(uint8_t p[4]) { 13 | uint32_t value = p[3]; 14 | 15 | value = (value << 8) | p[2]; 16 | value = (value << 8) | p[1]; 17 | value = (value << 8) | p[0]; 18 | 19 | return value; 20 | } 21 | 22 | static inline uint32_t rotl32(uint32_t x, int n) { 23 | // http://blog.regehr.org/archives/1063 24 | return x << n | (x >> (-n & 31)); 25 | } 26 | 27 | // https://tools.ietf.org/html/rfc7539#section-2.1 28 | static void chacha20_quarterround(uint32_t *x, int a, int b, int c, int d) { 29 | x[a] += x[b]; x[d] = rotl32(x[d] ^ x[a], 16); 30 | x[c] += x[d]; x[b] = rotl32(x[b] ^ x[c], 12); 31 | x[a] += x[b]; x[d] = rotl32(x[d] ^ x[a], 8); 32 | x[c] += x[d]; x[b] = rotl32(x[b] ^ x[c], 7); 33 | } 34 | 35 | static void chacha20_serialize(uint32_t in[16], uint8_t output[64]) { 36 | int i; 37 | for (i = 0; i < 16; i++) { 38 | u32t8le(in[i], output + (i << 2)); 39 | } 40 | } 41 | 42 | static void chacha20_block(uint32_t in[16], uint8_t out[64], int num_rounds) { 43 | int i; 44 | uint32_t x[16]; 45 | 46 | memcpy(x, in, sizeof(uint32_t) * 16); 47 | 48 | for (i = num_rounds; i > 0; i -= 2) { 49 | chacha20_quarterround(x, 0, 4, 8, 12); 50 | chacha20_quarterround(x, 1, 5, 9, 13); 51 | chacha20_quarterround(x, 2, 6, 10, 14); 52 | chacha20_quarterround(x, 3, 7, 11, 15); 53 | chacha20_quarterround(x, 0, 5, 10, 15); 54 | chacha20_quarterround(x, 1, 6, 11, 12); 55 | chacha20_quarterround(x, 2, 7, 8, 13); 56 | chacha20_quarterround(x, 3, 4, 9, 14); 57 | } 58 | 59 | for (i = 0; i < 16; i++) { 60 | x[i] += in[i]; 61 | } 62 | 63 | chacha20_serialize(x, out); 64 | } 65 | 66 | // https://tools.ietf.org/html/rfc7539#section-2.3 67 | static void chacha20_init_state(uint32_t s[16], uint8_t key[32], uint32_t counter, uint8_t nonce[12]) { 68 | int i; 69 | 70 | // refer: https://dxr.mozilla.org/mozilla-beta/source/security/nss/lib/freebl/chacha20.c 71 | // convert magic number to string: "expand 32-byte k" 72 | s[0] = 0x61707865; 73 | s[1] = 0x3320646e; 74 | s[2] = 0x79622d32; 75 | s[3] = 0x6b206574; 76 | 77 | for (i = 0; i < 8; i++) { 78 | s[4 + i] = u8t32le(key + i * 4); 79 | } 80 | 81 | s[12] = counter; 82 | 83 | for (i = 0; i < 3; i++) { 84 | s[13 + i] = u8t32le(nonce + i * 4); 85 | } 86 | } 87 | 88 | void ChaCha20XOR(uint8_t key[32], uint32_t counter, uint8_t nonce[12], uint8_t *in, uint8_t *out, int inlen) { 89 | int i, j; 90 | 91 | uint32_t s[16]; 92 | uint8_t block[64]; 93 | 94 | chacha20_init_state(s, key, counter, nonce); 95 | 96 | for (i = 0; i < inlen; i += 64) { 97 | chacha20_block(s, block, 20); 98 | s[12]++; 99 | 100 | for (j = i; j < i + 64; j++) { 101 | if (j >= inlen) { 102 | break; 103 | } 104 | out[j] = in[j] ^ block[j - i]; 105 | } 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /src/chacha20.h: -------------------------------------------------------------------------------- 1 | #ifndef __CHACHA20_H 2 | #define __CHACHA20_H 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | #include 9 | 10 | void ChaCha20XOR(uint8_t key[32], uint32_t counter, uint8_t nonce[12], uint8_t *input, uint8_t *output, int inputlen); 11 | 12 | #ifdef __cplusplus 13 | } 14 | #endif 15 | 16 | #endif 17 | -------------------------------------------------------------------------------- /test/chacha20_test.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "minunit.h" 3 | #include "chacha20.c" 4 | 5 | MU_TEST(u32t8le_test) { 6 | uint32_t value = 0x01020304; 7 | uint8_t p[4]; 8 | 9 | u32t8le(value, p); 10 | 11 | mu_check(p[0] == 0x04); 12 | mu_check(p[1] == 0x03); 13 | mu_check(p[2] == 0x02); 14 | mu_check(p[3] == 0x01); 15 | } 16 | 17 | MU_TEST(u8t32le_test) { 18 | uint32_t value = 0x01020304; 19 | uint8_t p[4] = { 0x04, 0x03, 0x02, 0x01 }; 20 | 21 | mu_check(u8t32le(p) == value); 22 | } 23 | 24 | MU_TEST(rotl32_test) { 25 | mu_check(rotl32(0x01020304, 8) == 0x02030401); 26 | } 27 | 28 | // https://tools.ietf.org/html/rfc7539#section-2.1.1 29 | MU_TEST(chacha20_quarterround_test_1) { 30 | int i; 31 | uint32_t before[] = { 0x11111111, 0x01020304, 0x9b8d6f43, 0x01234567 }; 32 | uint32_t after[] = { 0xea2a92f4, 0xcb1cf8ce, 0x4581472e, 0x5881c4bb }; 33 | 34 | chacha20_quarterround(before, 0, 1, 2, 3); 35 | 36 | for (i = 0; i < 4; i++) { 37 | mu_check(before[i] == after[i]); 38 | } 39 | } 40 | 41 | // https://tools.ietf.org/html/rfc7539#section-2.2.1 42 | MU_TEST(chacha20_quarterround_test_2) { 43 | int i; 44 | uint32_t before[] = { 45 | 0x879531e0, 0xc5ecf37d, 0x516461b1, 0xc9a62f8a, 46 | 0x44c20ef3, 0x3390af7f, 0xd9fc690b, 0x2a5f714c, 47 | 0x53372767, 0xb00a5631, 0x974c541a, 0x359e9963, 48 | 0x5c971061, 0x3d631689, 0x2098d9d6, 0x91dbd320 49 | }; 50 | uint32_t after[] = { 51 | 0x879531e0, 0xc5ecf37d, 0xbdb886dc, 0xc9a62f8a, 52 | 0x44c20ef3, 0x3390af7f, 0xd9fc690b, 0xcfacafd2, 53 | 0xe46bea80, 0xb00a5631, 0x974c541a, 0x359e9963, 54 | 0x5c971061, 0xccc07c79, 0x2098d9d6, 0x91dbd320 55 | }; 56 | 57 | chacha20_quarterround(before, 2, 7, 8, 13); 58 | 59 | for (i = 0; i < 16; i++) { 60 | mu_check(before[i] == after[i]); 61 | } 62 | } 63 | 64 | // https://tools.ietf.org/html/rfc7539#section-2.3.2 65 | MU_TEST(chacha20_block_test) { 66 | int i; 67 | uint32_t s[16] = { 68 | 0x61707865, 0x3320646e, 0x79622d32, 0x6b206574, 69 | 0x03020100, 0x07060504, 0x0b0a0908, 0x0f0e0d0c, 70 | 0x13121110, 0x17161514, 0x1b1a1918, 0x1f1e1d1c, 71 | 0x00000001, 0x09000000, 0x4a000000, 0x00000000 72 | }; 73 | 74 | uint8_t expect[] = { 75 | 0x10, 0xf1, 0xe7, 0xe4, 0xd1, 0x3b, 0x59, 0x15, 0x50, 0x0f, 0xdd, 0x1f, 0xa3, 0x20, 0x71, 0xc4, 76 | 0xc7, 0xd1, 0xf4, 0xc7, 0x33, 0xc0, 0x68, 0x03, 0x04, 0x22, 0xaa, 0x9a, 0xc3, 0xd4, 0x6c, 0x4e, 77 | 0xd2, 0x82, 0x64, 0x46, 0x07, 0x9f, 0xaa, 0x09, 0x14, 0xc2, 0xd7, 0x05, 0xd9, 0x8b, 0x02, 0xa2, 78 | 0xb5, 0x12, 0x9c, 0xd1, 0xde, 0x16, 0x4e, 0xb9, 0xcb, 0xd0, 0x83, 0xe8, 0xa2, 0x50, 0x3c, 0x4e 79 | }; 80 | 81 | uint8_t block[64]; 82 | 83 | chacha20_block(s, block, 20); 84 | 85 | for (i = 0; i < 16; i++) { 86 | mu_check(block[i] == expect[i]); 87 | } 88 | } 89 | 90 | MU_TEST(chacha20_serialize_test) { 91 | int i; 92 | uint32_t input[16] = { 93 | 0xe4e7f110, 0x15593bd1, 0x1fdd0f50, 0xc47120a3, 94 | 0xc7f4d1c7, 0x0368c033, 0x9aaa2204, 0x4e6cd4c3, 95 | 0x466482d2, 0x09aa9f07, 0x05d7c214, 0xa2028bd9, 96 | 0xd19c12b5, 0xb94e16de, 0xe883d0cb, 0x4e3c50a2 97 | }; 98 | 99 | uint8_t expect[64] = { 100 | 0x10, 0xf1, 0xe7, 0xe4, 0xd1, 0x3b, 0x59, 0x15, 0x50, 0x0f, 0xdd, 0x1f, 0xa3, 0x20, 0x71, 0xc4, 101 | 0xc7, 0xd1, 0xf4, 0xc7, 0x33, 0xc0, 0x68, 0x03, 0x04, 0x22, 0xaa, 0x9a, 0xc3, 0xd4, 0x6c, 0x4e, 102 | 0xd2, 0x82, 0x64, 0x46, 0x07, 0x9f, 0xaa, 0x09, 0x14, 0xc2, 0xd7, 0x05, 0xd9, 0x8b, 0x02, 0xa2, 103 | 0xb5, 0x12, 0x9c, 0xd1, 0xde, 0x16, 0x4e, 0xb9, 0xcb, 0xd0, 0x83, 0xe8, 0xa2, 0x50, 0x3c, 0x4e, 104 | }; 105 | uint8_t output[64]; 106 | 107 | chacha20_serialize(input, output); 108 | 109 | for (i = 0; i < 64; i++) { 110 | mu_check(output[i] == expect[i]); 111 | } 112 | } 113 | 114 | // https://tools.ietf.org/html/rfc7539#section-2.3.2 115 | MU_TEST(chacha20_init_state_test) { 116 | int i; 117 | 118 | uint8_t key[] = { 119 | 0x00, 0x01, 0x02, 0x03, 120 | 0x04, 0x05, 0x06, 0x07, 121 | 0x08, 0x09, 0x0a, 0x0b, 122 | 0x0c, 0x0d, 0x0e, 0x0f, 123 | 0x10, 0x11, 0x12, 0x13, 124 | 0x14, 0x15, 0x16, 0x17, 125 | 0x18, 0x19, 0x1a, 0x1b, 126 | 0x1c, 0x1d, 0x1e, 0x1f 127 | }; 128 | uint8_t nonce[] = { 129 | 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x4a, 0x00, 0x00, 0x00, 0x00 130 | }; 131 | uint32_t s[16]; 132 | uint32_t expect[16] = { 133 | 0x61707865, 0x3320646e, 0x79622d32, 0x6b206574, 134 | 0x03020100, 0x07060504, 0x0b0a0908, 0x0f0e0d0c, 135 | 0x13121110, 0x17161514, 0x1b1a1918, 0x1f1e1d1c, 136 | 0x00000001, 0x09000000, 0x4a000000, 0x00000000 137 | }; 138 | 139 | chacha20_init_state(s, key, 1, nonce); 140 | 141 | for (i = 0; i < 16; i++) { 142 | mu_check(s[i] == expect[i]); 143 | } 144 | } 145 | 146 | // https://tools.ietf.org/html/rfc7539#section-2.4.2 147 | MU_TEST(ChaCha20XOR_test) { 148 | int i; 149 | 150 | uint8_t key[] = { 151 | 0x00, 0x01, 0x02, 0x03, 152 | 0x04, 0x05, 0x06, 0x07, 153 | 0x08, 0x09, 0x0a, 0x0b, 154 | 0x0c, 0x0d, 0x0e, 0x0f, 155 | 0x10, 0x11, 0x12, 0x13, 156 | 0x14, 0x15, 0x16, 0x17, 157 | 0x18, 0x19, 0x1a, 0x1b, 158 | 0x1c, 0x1d, 0x1e, 0x1f 159 | }; 160 | uint8_t nonce[] = { 161 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4a, 0x00, 0x00, 0x00, 0x00 162 | }; 163 | 164 | uint8_t input[114] = { 165 | 0x4c, 0x61, 0x64, 0x69, 0x65, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x47, 0x65, 0x6e, 0x74, 0x6c, 166 | 0x65, 0x6d, 0x65, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x61, 0x73, 167 | 0x73, 0x20, 0x6f, 0x66, 0x20, 0x27, 0x39, 0x39, 0x3a, 0x20, 0x49, 0x66, 0x20, 0x49, 0x20, 0x63, 168 | 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x6f, 0x66, 0x66, 0x65, 0x72, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x6f, 169 | 0x6e, 0x6c, 0x79, 0x20, 0x6f, 0x6e, 0x65, 0x20, 0x74, 0x69, 0x70, 0x20, 0x66, 0x6f, 0x72, 0x20, 170 | 0x74, 0x68, 0x65, 0x20, 0x66, 0x75, 0x74, 0x75, 0x72, 0x65, 0x2c, 0x20, 0x73, 0x75, 0x6e, 0x73, 171 | 0x63, 0x72, 0x65, 0x65, 0x6e, 0x20, 0x77, 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x62, 0x65, 0x20, 0x69, 172 | 0x74, 0x2e 173 | }; 174 | 175 | uint8_t expect[114] = { 176 | 0x6e, 0x2e, 0x35, 0x9a, 0x25, 0x68, 0xf9, 0x80, 0x41, 0xba, 0x07, 0x28, 0xdd, 0x0d, 0x69, 0x81, 177 | 0xe9, 0x7e, 0x7a, 0xec, 0x1d, 0x43, 0x60, 0xc2, 0x0a, 0x27, 0xaf, 0xcc, 0xfd, 0x9f, 0xae, 0x0b, 178 | 0xf9, 0x1b, 0x65, 0xc5, 0x52, 0x47, 0x33, 0xab, 0x8f, 0x59, 0x3d, 0xab, 0xcd, 0x62, 0xb3, 0x57, 179 | 0x16, 0x39, 0xd6, 0x24, 0xe6, 0x51, 0x52, 0xab, 0x8f, 0x53, 0x0c, 0x35, 0x9f, 0x08, 0x61, 0xd8, 180 | 0x07, 0xca, 0x0d, 0xbf, 0x50, 0x0d, 0x6a, 0x61, 0x56, 0xa3, 0x8e, 0x08, 0x8a, 0x22, 0xb6, 0x5e, 181 | 0x52, 0xbc, 0x51, 0x4d, 0x16, 0xcc, 0xf8, 0x06, 0x81, 0x8c, 0xe9, 0x1a, 0xb7, 0x79, 0x37, 0x36, 182 | 0x5a, 0xf9, 0x0b, 0xbf, 0x74, 0xa3, 0x5b, 0xe6, 0xb4, 0x0b, 0x8e, 0xed, 0xf2, 0x78, 0x5e, 0x42, 183 | 0x87, 0x4d 184 | }; 185 | 186 | uint8_t output[115]; 187 | output[114] = 0xff; // this should not changed 188 | 189 | ChaCha20XOR(key, 1, nonce, input, output, 114); 190 | 191 | for (i = 0; i < 114; i++) { 192 | mu_check(output[i] == expect[i]); 193 | } 194 | 195 | mu_check(output[114] == 0xff); 196 | } 197 | 198 | int main(int argc, char **argv) { 199 | MU_RUN_TEST(u32t8le_test); 200 | MU_RUN_TEST(u8t32le_test); 201 | 202 | MU_RUN_TEST(rotl32_test); 203 | 204 | MU_RUN_TEST(chacha20_block_test); 205 | 206 | MU_RUN_TEST(chacha20_serialize_test); 207 | 208 | MU_RUN_TEST(chacha20_quarterround_test_1); 209 | MU_RUN_TEST(chacha20_quarterround_test_2); 210 | 211 | MU_RUN_TEST(chacha20_init_state_test); 212 | 213 | MU_RUN_TEST(ChaCha20XOR_test); 214 | 215 | MU_REPORT(); 216 | return 0; 217 | } -------------------------------------------------------------------------------- /test/minunit.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2012 David Siñuela Pastor, siu.4coders@gmail.com 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining 5 | * a copy of this software and associated documentation files (the 6 | * "Software"), to deal in the Software without restriction, including 7 | * without limitation the rights to use, copy, modify, merge, publish, 8 | * distribute, sublicense, and/or sell copies of the Software, and to 9 | * permit persons to whom the Software is furnished to do so, subject to 10 | * the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be 13 | * included in all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 19 | * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 20 | * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 21 | * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | */ 23 | #ifndef __MINUNIT_H__ 24 | #define __MINUNIT_H__ 25 | 26 | #ifdef __cplusplus 27 | extern "C" { 28 | #endif 29 | 30 | #if defined(_WIN32) 31 | #include 32 | 33 | #elif defined(__unix__) || defined(__unix) || defined(unix) || (defined(__APPLE__) && defined(__MACH__)) 34 | 35 | /* Change POSIX C SOURCE version for pure c99 compilers */ 36 | #if !defined(_POSIX_C_SOURCE) || _POSIX_C_SOURCE < 200112L 37 | #undef _POSIX_C_SOURCE 38 | #define _POSIX_C_SOURCE 200112L 39 | #endif 40 | 41 | #include /* POSIX flags */ 42 | #include /* clock_gettime(), time() */ 43 | #include /* gethrtime(), gettimeofday() */ 44 | #include 45 | #include 46 | 47 | #if defined(__MACH__) && defined(__APPLE__) 48 | #include 49 | #include 50 | #endif 51 | 52 | #else 53 | #error "Unable to define timers for an unknown OS." 54 | #endif 55 | 56 | #include 57 | #include 58 | 59 | /* Maximum length of last message */ 60 | #define MINUNIT_MESSAGE_LEN 1024 61 | /* Do not change */ 62 | #define MINUNIT_EPSILON 1E-12 63 | 64 | /* Misc. counters */ 65 | static int minunit_run = 0; 66 | static int minunit_assert = 0; 67 | static int minunit_fail = 0; 68 | static int minunit_status = 0; 69 | 70 | /* Timers */ 71 | static double minunit_real_timer = 0; 72 | static double minunit_proc_timer = 0; 73 | 74 | /* Last message */ 75 | static char minunit_last_message[MINUNIT_MESSAGE_LEN]; 76 | 77 | /* Test setup and teardown function pointers */ 78 | static void (*minunit_setup)(void) = NULL; 79 | static void (*minunit_teardown)(void) = NULL; 80 | 81 | /* Definitions */ 82 | #define MU_TEST(method_name) static void method_name() 83 | #define MU_TEST_SUITE(suite_name) static void suite_name() 84 | 85 | #define MU__SAFE_BLOCK(block) do {\ 86 | block\ 87 | } while(0) 88 | 89 | /* Run test suite and unset setup and teardown functions */ 90 | #define MU_RUN_SUITE(suite_name) MU__SAFE_BLOCK(\ 91 | suite_name();\ 92 | minunit_setup = NULL;\ 93 | minunit_teardown = NULL;\ 94 | ) 95 | 96 | /* Configure setup and teardown functions */ 97 | #define MU_SUITE_CONFIGURE(setup_fun, teardown_fun) MU__SAFE_BLOCK(\ 98 | minunit_setup = setup_fun;\ 99 | minunit_teardown = teardown_fun;\ 100 | ) 101 | 102 | /* Test runner */ 103 | #define MU_RUN_TEST(test) MU__SAFE_BLOCK(\ 104 | if (minunit_real_timer==0 && minunit_real_timer==0) {\ 105 | minunit_real_timer = mu_timer_real();\ 106 | minunit_proc_timer = mu_timer_cpu();\ 107 | }\ 108 | if (minunit_setup) (*minunit_setup)();\ 109 | minunit_status = 0;\ 110 | test();\ 111 | minunit_run++;\ 112 | if (minunit_status) {\ 113 | minunit_fail++;\ 114 | printf("F");\ 115 | printf("\n%s\n", minunit_last_message);\ 116 | }\ 117 | fflush(stdout);\ 118 | if (minunit_teardown) (*minunit_teardown)();\ 119 | ) 120 | 121 | /* Report */ 122 | #define MU_REPORT() MU__SAFE_BLOCK(\ 123 | double minunit_end_real_timer;\ 124 | double minunit_end_proc_timer;\ 125 | printf("\n\n%d tests, %d assertions, %d failures\n", minunit_run, minunit_assert, minunit_fail);\ 126 | minunit_end_real_timer = mu_timer_real();\ 127 | minunit_end_proc_timer = mu_timer_cpu();\ 128 | printf("\nFinished in %.8f seconds (real) %.8f seconds (proc)\n\n",\ 129 | minunit_end_real_timer - minunit_real_timer,\ 130 | minunit_end_proc_timer - minunit_proc_timer);\ 131 | ) 132 | 133 | /* Assertions */ 134 | #define mu_check(test) MU__SAFE_BLOCK(\ 135 | minunit_assert++;\ 136 | if (!(test)) {\ 137 | snprintf(minunit_last_message, MINUNIT_MESSAGE_LEN, "%s failed:\n\t%s:%d: %s", __func__, __FILE__, __LINE__, #test);\ 138 | minunit_status = 1;\ 139 | return;\ 140 | } else {\ 141 | printf(".");\ 142 | }\ 143 | ) 144 | 145 | #define mu_fail(message) MU__SAFE_BLOCK(\ 146 | minunit_assert++;\ 147 | snprintf(minunit_last_message, MINUNIT_MESSAGE_LEN, "%s failed:\n\t%s:%d: %s", __func__, __FILE__, __LINE__, message);\ 148 | minunit_status = 1;\ 149 | return;\ 150 | ) 151 | 152 | #define mu_assert(test, message) MU__SAFE_BLOCK(\ 153 | minunit_assert++;\ 154 | if (!(test)) {\ 155 | snprintf(minunit_last_message, MINUNIT_MESSAGE_LEN, "%s failed:\n\t%s:%d: %s", __func__, __FILE__, __LINE__, message);\ 156 | minunit_status = 1;\ 157 | return;\ 158 | } else {\ 159 | printf(".");\ 160 | }\ 161 | ) 162 | 163 | #define mu_assert_int_eq(expected, result) MU__SAFE_BLOCK(\ 164 | int minunit_tmp_e;\ 165 | int minunit_tmp_r;\ 166 | minunit_assert++;\ 167 | minunit_tmp_e = (expected);\ 168 | minunit_tmp_r = (result);\ 169 | if (minunit_tmp_e != minunit_tmp_r) {\ 170 | snprintf(minunit_last_message, MINUNIT_MESSAGE_LEN, "%s failed:\n\t%s:%d: %d expected but was %d", __func__, __FILE__, __LINE__, minunit_tmp_e, minunit_tmp_r);\ 171 | minunit_status = 1;\ 172 | return;\ 173 | } else {\ 174 | printf(".");\ 175 | }\ 176 | ) 177 | 178 | #define mu_assert_double_eq(expected, result) MU__SAFE_BLOCK(\ 179 | double minunit_tmp_e;\ 180 | double minunit_tmp_r;\ 181 | minunit_assert++;\ 182 | minunit_tmp_e = (expected);\ 183 | minunit_tmp_r = (result);\ 184 | if (fabs(minunit_tmp_e-minunit_tmp_r) > MINUNIT_EPSILON) {\ 185 | snprintf(minunit_last_message, MINUNIT_MESSAGE_LEN, "%s failed:\n\t%s:%d: %g expected but was %g", __func__, __FILE__, __LINE__, minunit_tmp_e, minunit_tmp_r);\ 186 | minunit_status = 1;\ 187 | return;\ 188 | } else {\ 189 | printf(".");\ 190 | }\ 191 | ) 192 | 193 | /* 194 | * The following two functions were written by David Robert Nadeau 195 | * from http://NadeauSoftware.com/ and distributed under the 196 | * Creative Commons Attribution 3.0 Unported License 197 | */ 198 | 199 | /** 200 | * Returns the real time, in seconds, or -1.0 if an error occurred. 201 | * 202 | * Time is measured since an arbitrary and OS-dependent start time. 203 | * The returned real time is only useful for computing an elapsed time 204 | * between two calls to this function. 205 | */ 206 | static double mu_timer_real( ) 207 | { 208 | #if defined(_WIN32) 209 | FILETIME tm; 210 | ULONGLONG t; 211 | #if defined(NTDDI_WIN8) && NTDDI_VERSION >= NTDDI_WIN8 212 | /* Windows 8, Windows Server 2012 and later. ---------------- */ 213 | GetSystemTimePreciseAsFileTime( &tm ); 214 | #else 215 | /* Windows 2000 and later. ---------------------------------- */ 216 | GetSystemTimeAsFileTime( &tm ); 217 | #endif 218 | t = ((ULONGLONG)tm.dwHighDateTime << 32) | (ULONGLONG)tm.dwLowDateTime; 219 | return (double)t / 10000000.0; 220 | 221 | #elif (defined(__hpux) || defined(hpux)) || ((defined(__sun__) || defined(__sun) || defined(sun)) && (defined(__SVR4) || defined(__svr4__))) 222 | /* HP-UX, Solaris. ------------------------------------------ */ 223 | return (double)gethrtime( ) / 1000000000.0; 224 | 225 | #elif defined(__MACH__) && defined(__APPLE__) 226 | /* OSX. ----------------------------------------------------- */ 227 | static double timeConvert = 0.0; 228 | if ( timeConvert == 0.0 ) 229 | { 230 | mach_timebase_info_data_t timeBase; 231 | (void)mach_timebase_info( &timeBase ); 232 | timeConvert = (double)timeBase.numer / 233 | (double)timeBase.denom / 234 | 1000000000.0; 235 | } 236 | return (double)mach_absolute_time( ) * timeConvert; 237 | 238 | #elif defined(_POSIX_VERSION) 239 | /* POSIX. --------------------------------------------------- */ 240 | #if defined(_POSIX_TIMERS) && (_POSIX_TIMERS > 0) 241 | { 242 | struct timespec ts; 243 | #if defined(CLOCK_MONOTONIC_PRECISE) 244 | /* BSD. --------------------------------------------- */ 245 | const clockid_t id = CLOCK_MONOTONIC_PRECISE; 246 | #elif defined(CLOCK_MONOTONIC_RAW) 247 | /* Linux. ------------------------------------------- */ 248 | const clockid_t id = CLOCK_MONOTONIC_RAW; 249 | #elif defined(CLOCK_HIGHRES) 250 | /* Solaris. ----------------------------------------- */ 251 | const clockid_t id = CLOCK_HIGHRES; 252 | #elif defined(CLOCK_MONOTONIC) 253 | /* AIX, BSD, Linux, POSIX, Solaris. ----------------- */ 254 | const clockid_t id = CLOCK_MONOTONIC; 255 | #elif defined(CLOCK_REALTIME) 256 | /* AIX, BSD, HP-UX, Linux, POSIX. ------------------- */ 257 | const clockid_t id = CLOCK_REALTIME; 258 | #else 259 | const clockid_t id = (clockid_t)-1; /* Unknown. */ 260 | #endif /* CLOCK_* */ 261 | if ( id != (clockid_t)-1 && clock_gettime( id, &ts ) != -1 ) 262 | return (double)ts.tv_sec + 263 | (double)ts.tv_nsec / 1000000000.0; 264 | /* Fall thru. */ 265 | } 266 | #endif /* _POSIX_TIMERS */ 267 | 268 | /* AIX, BSD, Cygwin, HP-UX, Linux, OSX, POSIX, Solaris. ----- */ 269 | struct timeval tm; 270 | gettimeofday( &tm, NULL ); 271 | return (double)tm.tv_sec + (double)tm.tv_usec / 1000000.0; 272 | #else 273 | return -1.0; /* Failed. */ 274 | #endif 275 | } 276 | 277 | /** 278 | * Returns the amount of CPU time used by the current process, 279 | * in seconds, or -1.0 if an error occurred. 280 | */ 281 | static double mu_timer_cpu( ) 282 | { 283 | #if defined(_WIN32) 284 | /* Windows -------------------------------------------------- */ 285 | FILETIME createTime; 286 | FILETIME exitTime; 287 | FILETIME kernelTime; 288 | FILETIME userTime; 289 | if ( GetProcessTimes( GetCurrentProcess( ), 290 | &createTime, &exitTime, &kernelTime, &userTime ) != -1 ) 291 | { 292 | SYSTEMTIME userSystemTime; 293 | if ( FileTimeToSystemTime( &userTime, &userSystemTime ) != -1 ) 294 | return (double)userSystemTime.wHour * 3600.0 + 295 | (double)userSystemTime.wMinute * 60.0 + 296 | (double)userSystemTime.wSecond + 297 | (double)userSystemTime.wMilliseconds / 1000.0; 298 | } 299 | 300 | #elif defined(__unix__) || defined(__unix) || defined(unix) || (defined(__APPLE__) && defined(__MACH__)) 301 | /* AIX, BSD, Cygwin, HP-UX, Linux, OSX, and Solaris --------- */ 302 | 303 | #if defined(_POSIX_TIMERS) && (_POSIX_TIMERS > 0) 304 | /* Prefer high-res POSIX timers, when available. */ 305 | { 306 | clockid_t id; 307 | struct timespec ts; 308 | #if _POSIX_CPUTIME > 0 309 | /* Clock ids vary by OS. Query the id, if possible. */ 310 | if ( clock_getcpuclockid( 0, &id ) == -1 ) 311 | #endif 312 | #if defined(CLOCK_PROCESS_CPUTIME_ID) 313 | /* Use known clock id for AIX, Linux, or Solaris. */ 314 | id = CLOCK_PROCESS_CPUTIME_ID; 315 | #elif defined(CLOCK_VIRTUAL) 316 | /* Use known clock id for BSD or HP-UX. */ 317 | id = CLOCK_VIRTUAL; 318 | #else 319 | id = (clockid_t)-1; 320 | #endif 321 | if ( id != (clockid_t)-1 && clock_gettime( id, &ts ) != -1 ) 322 | return (double)ts.tv_sec + 323 | (double)ts.tv_nsec / 1000000000.0; 324 | } 325 | #endif 326 | 327 | #if defined(RUSAGE_SELF) 328 | { 329 | struct rusage rusage; 330 | if ( getrusage( RUSAGE_SELF, &rusage ) != -1 ) 331 | return (double)rusage.ru_utime.tv_sec + 332 | (double)rusage.ru_utime.tv_usec / 1000000.0; 333 | } 334 | #endif 335 | 336 | #if defined(_SC_CLK_TCK) 337 | { 338 | const double ticks = (double)sysconf( _SC_CLK_TCK ); 339 | struct tms tms; 340 | if ( times( &tms ) != (clock_t)-1 ) 341 | return (double)tms.tms_utime / ticks; 342 | } 343 | #endif 344 | 345 | #if defined(CLOCKS_PER_SEC) 346 | { 347 | clock_t cl = clock( ); 348 | if ( cl != (clock_t)-1 ) 349 | return (double)cl / (double)CLOCKS_PER_SEC; 350 | } 351 | #endif 352 | 353 | #endif 354 | 355 | return -1; /* Failed. */ 356 | } 357 | 358 | #ifdef __cplusplus 359 | } 360 | #endif 361 | 362 | #endif /* __MINUNIT_H__ */ --------------------------------------------------------------------------------