├── .gitignore ├── LICENSE ├── Makefile ├── README.md ├── chacha20poly1305.c ├── chacha20poly1305.h ├── chacha_merged.c ├── ecrypt-config.h ├── ecrypt-machine.h ├── ecrypt-portable.h ├── ecrypt-sync.h ├── poly1305-donna-16.h ├── poly1305-donna.c ├── poly1305-donna.h ├── rfc7539.c ├── rfc7539.h └── rfc7539_test.c /.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (C) 2016 Will Glozer 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 13 | all 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 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | CFLAGS := -Wall -Wextra 2 | 3 | test: rfc7539_test 4 | ./rfc7539_test 5 | 6 | chacha20poly1305.o: chacha20poly1305.c chacha20.o poly1305.o 7 | $(CC) $(CFLAGS) -c -o $@ $< 8 | 9 | chacha20.o: chacha_merged.c 10 | $(CC) $(CFLAGS) -c -o $@ $< 11 | 12 | poly1305.o: poly1305-donna.c 13 | $(CC) $(CFLAGS) -DPOLY1305_16BIT -c -o $@ $< 14 | 15 | rfc7539_test: rfc7539.c chacha20poly1305.o poly1305.o chacha20.o 16 | 17 | .PHONY: test 18 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Implementations of the ChaCha20 + Poly1305 and XChaCha20 + Poly1305 2 | AEAD constructions with a goal of simplicity and correctness rather 3 | than performance. 4 | 5 | ## About 6 | 7 | This code provides a portable C reference implementation of two 8 | AEAD constructions built on top of the ChaCha20 reference 9 | implementation from [SUPERCOP](https://bench.cr.yp.to/supercop.html) 10 | and [Poly1305-donna](https://github.com/floodyberry/poly1305-donna). 11 | 12 | One construction is XChaCha20 + Poly1305 in a style similar to 13 | [NaCl](https://nacl.cr.yp.to/)'s `crypto_secretbox_xsalsa20poly1305` 14 | but using XChaCha20 instead of XSalsa20. 15 | 16 | The other construction is ChaCha20 + Poly1305 as specified in 17 | [RFC 7539](https://tools.ietf.org/html/rfc7539). 18 | 19 | ## License 20 | 21 | Copyright (C) 2016 Will Glozer. 22 | 23 | Permission is hereby granted, free of charge, to any person obtaining a copy 24 | of this software and associated documentation files (the "Software"), to deal 25 | in the Software without restriction, including without limitation the rights 26 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 27 | copies of the Software, and to permit persons to whom the Software is 28 | furnished to do so, subject to the following conditions: 29 | 30 | The above copyright notice and this permission notice shall be included in 31 | all copies or substantial portions of the Software. 32 | 33 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 34 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 35 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 36 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 37 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 38 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 39 | THE SOFTWARE. 40 | 41 | ## Cryptography Notice 42 | 43 | This distribution includes cryptographic software. The country in 44 | which you currently reside may have restrictions on the import, 45 | possession, use, and/or re-export to another country, of encryption 46 | software. BEFORE using any encryption software, please check your 47 | country's laws, regulations and policies concerning the import, 48 | possession, or use, and re-export of encryption software, to see if 49 | this is permitted. See for more 50 | information. 51 | 52 | The U.S. Government Department of Commerce, Bureau of Industry and 53 | Security (BIS), has classified this software as Export Commodity 54 | Control Number (ECCN) 5D002.C.1, which includes information security 55 | software using or performing cryptographic functions with asymmetric 56 | algorithms. The form and manner of this distribution makes it 57 | eligible for export under the License Exception ENC Technology 58 | Software Unrestricted (TSU) exception (see the BIS Export 59 | Administration Regulations, Section 740.13) for both object code and 60 | source code. 61 | -------------------------------------------------------------------------------- /chacha20poly1305.c: -------------------------------------------------------------------------------- 1 | // Implementations of the XChaCha20 + Poly1305 and ChaCha20 + Poly1305 2 | // AEAD constructions with a goal of simplicity and correctness rather 3 | // than performance. 4 | 5 | #include "chacha20poly1305.h" 6 | 7 | void hchacha20(ECRYPT_ctx *x,u8 *c); 8 | 9 | // Initialize the XChaCha20 + Poly1305 context for encryption or decryption 10 | // using a 32 byte key and 24 byte nonce. The key and the first 16 bytes of 11 | // the nonce are used as input to HChaCha20 to derive the Chacha20 key. 12 | void xchacha20poly1305_init(chacha20poly1305_ctx *ctx, uint8_t key[32], uint8_t nonce[24]) { 13 | unsigned char subkey[32] = {0}; 14 | unsigned char block0[64] = {0}; 15 | ECRYPT_ctx tmp; 16 | 17 | // Generate the Chacha20 key by applying HChaCha20 to the 18 | // original key and the first 16 bytes of the nonce. 19 | ECRYPT_keysetup(&tmp, key, 256, 16); 20 | tmp.input[12] = U8TO32_LITTLE(nonce + 0); 21 | tmp.input[13] = U8TO32_LITTLE(nonce + 4); 22 | tmp.input[14] = U8TO32_LITTLE(nonce + 8); 23 | tmp.input[15] = U8TO32_LITTLE(nonce + 12); 24 | hchacha20(&tmp, subkey); 25 | 26 | // Initialize Chacha20 with the newly generated key and 27 | // the last 8 bytes of the nonce. 28 | ECRYPT_keysetup(&ctx->chacha20, subkey, 256, 16); 29 | ECRYPT_ivsetup(&ctx->chacha20, nonce+16); 30 | 31 | // Encrypt 64 bytes of zeros and use the first 32 bytes 32 | // as the Poly1305 key. 33 | ECRYPT_encrypt_bytes(&ctx->chacha20, block0, block0, 64); 34 | poly1305_init(&ctx->poly1305, block0); 35 | } 36 | 37 | // Encrypt n bytes of plaintext where n must be evenly divisible by the 38 | // Chacha20 blocksize of 64, except for the final n bytes of plaintext. 39 | void chacha20poly1305_encrypt(chacha20poly1305_ctx *ctx, uint8_t *in, uint8_t *out, size_t n) { 40 | ECRYPT_encrypt_bytes(&ctx->chacha20, in, out, n); 41 | poly1305_update(&ctx->poly1305, out, n); 42 | } 43 | 44 | // Decrypt n bytes of ciphertext where n must be evenly divisible by the 45 | // Chacha20 blocksize of 64, except for the final n bytes of ciphertext. 46 | void chacha20poly1305_decrypt(chacha20poly1305_ctx *ctx, uint8_t *in, uint8_t *out, size_t n) { 47 | poly1305_update(&ctx->poly1305, in, n); 48 | ECRYPT_encrypt_bytes(&ctx->chacha20, in, out, n); 49 | } 50 | 51 | // Include authenticated data in the Poly1305 MAC. 52 | void chacha20poly1305_auth(chacha20poly1305_ctx *ctx, uint8_t *in, size_t n) { 53 | poly1305_update(&ctx->poly1305, in, n); 54 | } 55 | 56 | // Compute NaCl secretbox-style Poly1305 MAC. 57 | void chacha20poly1305_finish(chacha20poly1305_ctx *ctx, uint8_t mac[16]) { 58 | poly1305_finish(&ctx->poly1305, mac); 59 | } 60 | -------------------------------------------------------------------------------- /chacha20poly1305.h: -------------------------------------------------------------------------------- 1 | #ifndef CHACHA20POLY1305_H 2 | #define CHACHA20POLY1305_H 3 | 4 | #include "ecrypt-sync.h" 5 | #include "poly1305-donna.h" 6 | 7 | typedef struct { 8 | ECRYPT_ctx chacha20; 9 | poly1305_context poly1305; 10 | } chacha20poly1305_ctx; 11 | 12 | void xchacha20poly1305_init(chacha20poly1305_ctx *ctx, uint8_t key[32], uint8_t nonce[24]); 13 | void chacha20poly1305_encrypt(chacha20poly1305_ctx *ctx, uint8_t *in, uint8_t *out, size_t n); 14 | void chacha20poly1305_decrypt(chacha20poly1305_ctx *ctx, uint8_t *in, uint8_t *out, size_t n); 15 | void chacha20poly1305_auth(chacha20poly1305_ctx *ctx, uint8_t *in, size_t n); 16 | void chacha20poly1305_finish(chacha20poly1305_ctx *ctx, uint8_t mac[16]); 17 | 18 | #endif // CHACHA20POLY1305_H 19 | -------------------------------------------------------------------------------- /chacha_merged.c: -------------------------------------------------------------------------------- 1 | /* 2 | chacha-merged.c version 20080118 3 | D. J. Bernstein 4 | Public domain. 5 | */ 6 | 7 | #include "ecrypt-sync.h" 8 | 9 | #define ROTATE(v,c) (ROTL32(v,c)) 10 | #define XOR(v,w) ((v) ^ (w)) 11 | #define PLUS(v,w) (U32V((v) + (w))) 12 | #define PLUSONE(v) (PLUS((v),1)) 13 | 14 | #define QUARTERROUND(a,b,c,d) \ 15 | a = PLUS(a,b); d = ROTATE(XOR(d,a),16); \ 16 | c = PLUS(c,d); b = ROTATE(XOR(b,c),12); \ 17 | a = PLUS(a,b); d = ROTATE(XOR(d,a), 8); \ 18 | c = PLUS(c,d); b = ROTATE(XOR(b,c), 7); 19 | 20 | void ECRYPT_init(void) 21 | { 22 | return; 23 | } 24 | 25 | static const char sigma[16] = "expand 32-byte k"; 26 | static const char tau[16] = "expand 16-byte k"; 27 | 28 | void ECRYPT_keysetup(ECRYPT_ctx *x,const u8 *k,u32 kbits,u32 ivbits) 29 | { 30 | const char *constants; 31 | 32 | x->input[4] = U8TO32_LITTLE(k + 0); 33 | x->input[5] = U8TO32_LITTLE(k + 4); 34 | x->input[6] = U8TO32_LITTLE(k + 8); 35 | x->input[7] = U8TO32_LITTLE(k + 12); 36 | if (kbits == 256) { /* recommended */ 37 | k += 16; 38 | constants = sigma; 39 | } else { /* kbits == 128 */ 40 | constants = tau; 41 | } 42 | x->input[8] = U8TO32_LITTLE(k + 0); 43 | x->input[9] = U8TO32_LITTLE(k + 4); 44 | x->input[10] = U8TO32_LITTLE(k + 8); 45 | x->input[11] = U8TO32_LITTLE(k + 12); 46 | x->input[0] = U8TO32_LITTLE(constants + 0); 47 | x->input[1] = U8TO32_LITTLE(constants + 4); 48 | x->input[2] = U8TO32_LITTLE(constants + 8); 49 | x->input[3] = U8TO32_LITTLE(constants + 12); 50 | } 51 | 52 | void ECRYPT_ivsetup(ECRYPT_ctx *x,const u8 *iv) 53 | { 54 | x->input[12] = 0; 55 | x->input[13] = 0; 56 | x->input[14] = U8TO32_LITTLE(iv + 0); 57 | x->input[15] = U8TO32_LITTLE(iv + 4); 58 | } 59 | 60 | void ECRYPT_encrypt_bytes(ECRYPT_ctx *x,const u8 *m,u8 *c,u32 bytes) 61 | { 62 | u32 x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15; 63 | u32 j0, j1, j2, j3, j4, j5, j6, j7, j8, j9, j10, j11, j12, j13, j14, j15; 64 | u8 *ctarget; 65 | u8 tmp[64]; 66 | int i; 67 | 68 | if (!bytes) return; 69 | 70 | j0 = x->input[0]; 71 | j1 = x->input[1]; 72 | j2 = x->input[2]; 73 | j3 = x->input[3]; 74 | j4 = x->input[4]; 75 | j5 = x->input[5]; 76 | j6 = x->input[6]; 77 | j7 = x->input[7]; 78 | j8 = x->input[8]; 79 | j9 = x->input[9]; 80 | j10 = x->input[10]; 81 | j11 = x->input[11]; 82 | j12 = x->input[12]; 83 | j13 = x->input[13]; 84 | j14 = x->input[14]; 85 | j15 = x->input[15]; 86 | 87 | for (;;) { 88 | if (bytes < 64) { 89 | for (i = 0;i < bytes;++i) tmp[i] = m[i]; 90 | m = tmp; 91 | ctarget = c; 92 | c = tmp; 93 | } 94 | x0 = j0; 95 | x1 = j1; 96 | x2 = j2; 97 | x3 = j3; 98 | x4 = j4; 99 | x5 = j5; 100 | x6 = j6; 101 | x7 = j7; 102 | x8 = j8; 103 | x9 = j9; 104 | x10 = j10; 105 | x11 = j11; 106 | x12 = j12; 107 | x13 = j13; 108 | x14 = j14; 109 | x15 = j15; 110 | for (i = 20;i > 0;i -= 2) { 111 | QUARTERROUND( x0, x4, x8,x12) 112 | QUARTERROUND( x1, x5, x9,x13) 113 | QUARTERROUND( x2, x6,x10,x14) 114 | QUARTERROUND( x3, x7,x11,x15) 115 | QUARTERROUND( x0, x5,x10,x15) 116 | QUARTERROUND( x1, x6,x11,x12) 117 | QUARTERROUND( x2, x7, x8,x13) 118 | QUARTERROUND( x3, x4, x9,x14) 119 | } 120 | x0 = PLUS(x0,j0); 121 | x1 = PLUS(x1,j1); 122 | x2 = PLUS(x2,j2); 123 | x3 = PLUS(x3,j3); 124 | x4 = PLUS(x4,j4); 125 | x5 = PLUS(x5,j5); 126 | x6 = PLUS(x6,j6); 127 | x7 = PLUS(x7,j7); 128 | x8 = PLUS(x8,j8); 129 | x9 = PLUS(x9,j9); 130 | x10 = PLUS(x10,j10); 131 | x11 = PLUS(x11,j11); 132 | x12 = PLUS(x12,j12); 133 | x13 = PLUS(x13,j13); 134 | x14 = PLUS(x14,j14); 135 | x15 = PLUS(x15,j15); 136 | 137 | x0 = XOR(x0,U8TO32_LITTLE(m + 0)); 138 | x1 = XOR(x1,U8TO32_LITTLE(m + 4)); 139 | x2 = XOR(x2,U8TO32_LITTLE(m + 8)); 140 | x3 = XOR(x3,U8TO32_LITTLE(m + 12)); 141 | x4 = XOR(x4,U8TO32_LITTLE(m + 16)); 142 | x5 = XOR(x5,U8TO32_LITTLE(m + 20)); 143 | x6 = XOR(x6,U8TO32_LITTLE(m + 24)); 144 | x7 = XOR(x7,U8TO32_LITTLE(m + 28)); 145 | x8 = XOR(x8,U8TO32_LITTLE(m + 32)); 146 | x9 = XOR(x9,U8TO32_LITTLE(m + 36)); 147 | x10 = XOR(x10,U8TO32_LITTLE(m + 40)); 148 | x11 = XOR(x11,U8TO32_LITTLE(m + 44)); 149 | x12 = XOR(x12,U8TO32_LITTLE(m + 48)); 150 | x13 = XOR(x13,U8TO32_LITTLE(m + 52)); 151 | x14 = XOR(x14,U8TO32_LITTLE(m + 56)); 152 | x15 = XOR(x15,U8TO32_LITTLE(m + 60)); 153 | 154 | j12 = PLUSONE(j12); 155 | if (!j12) { 156 | j13 = PLUSONE(j13); 157 | /* stopping at 2^70 bytes per nonce is user's responsibility */ 158 | } 159 | 160 | U32TO8_LITTLE(c + 0,x0); 161 | U32TO8_LITTLE(c + 4,x1); 162 | U32TO8_LITTLE(c + 8,x2); 163 | U32TO8_LITTLE(c + 12,x3); 164 | U32TO8_LITTLE(c + 16,x4); 165 | U32TO8_LITTLE(c + 20,x5); 166 | U32TO8_LITTLE(c + 24,x6); 167 | U32TO8_LITTLE(c + 28,x7); 168 | U32TO8_LITTLE(c + 32,x8); 169 | U32TO8_LITTLE(c + 36,x9); 170 | U32TO8_LITTLE(c + 40,x10); 171 | U32TO8_LITTLE(c + 44,x11); 172 | U32TO8_LITTLE(c + 48,x12); 173 | U32TO8_LITTLE(c + 52,x13); 174 | U32TO8_LITTLE(c + 56,x14); 175 | U32TO8_LITTLE(c + 60,x15); 176 | 177 | if (bytes <= 64) { 178 | if (bytes < 64) { 179 | for (i = 0;i < bytes;++i) ctarget[i] = c[i]; 180 | } 181 | x->input[12] = j12; 182 | x->input[13] = j13; 183 | return; 184 | } 185 | bytes -= 64; 186 | c += 64; 187 | m += 64; 188 | } 189 | } 190 | 191 | void ECRYPT_decrypt_bytes(ECRYPT_ctx *x,const u8 *c,u8 *m,u32 bytes) 192 | { 193 | ECRYPT_encrypt_bytes(x,c,m,bytes); 194 | } 195 | 196 | void ECRYPT_keystream_bytes(ECRYPT_ctx *x,u8 *stream,u32 bytes) 197 | { 198 | u32 i; 199 | for (i = 0;i < bytes;++i) stream[i] = 0; 200 | ECRYPT_encrypt_bytes(x,stream,stream,bytes); 201 | } 202 | 203 | void hchacha20(ECRYPT_ctx *x,u8 *c) 204 | { 205 | u32 x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15; 206 | int i; 207 | 208 | x0 = x->input[0]; 209 | x1 = x->input[1]; 210 | x2 = x->input[2]; 211 | x3 = x->input[3]; 212 | x4 = x->input[4]; 213 | x5 = x->input[5]; 214 | x6 = x->input[6]; 215 | x7 = x->input[7]; 216 | x8 = x->input[8]; 217 | x9 = x->input[9]; 218 | x10 = x->input[10]; 219 | x11 = x->input[11]; 220 | x12 = x->input[12]; 221 | x13 = x->input[13]; 222 | x14 = x->input[14]; 223 | x15 = x->input[15]; 224 | 225 | for (i = 20;i > 0;i -= 2) { 226 | QUARTERROUND( x0, x4, x8,x12) 227 | QUARTERROUND( x1, x5, x9,x13) 228 | QUARTERROUND( x2, x6,x10,x14) 229 | QUARTERROUND( x3, x7,x11,x15) 230 | QUARTERROUND( x0, x5,x10,x15) 231 | QUARTERROUND( x1, x6,x11,x12) 232 | QUARTERROUND( x2, x7, x8,x13) 233 | QUARTERROUND( x3, x4, x9,x14) 234 | } 235 | 236 | U32TO8_LITTLE(c + 0,x0); 237 | U32TO8_LITTLE(c + 4,x1); 238 | U32TO8_LITTLE(c + 8,x2); 239 | U32TO8_LITTLE(c + 12,x3); 240 | U32TO8_LITTLE(c + 16,x12); 241 | U32TO8_LITTLE(c + 20,x13); 242 | U32TO8_LITTLE(c + 24,x14); 243 | U32TO8_LITTLE(c + 28,x15); 244 | } 245 | -------------------------------------------------------------------------------- /ecrypt-config.h: -------------------------------------------------------------------------------- 1 | /* ecrypt-config.h */ 2 | 3 | /* *** Normally, it should not be necessary to edit this file. *** */ 4 | 5 | #ifndef ECRYPT_CONFIG 6 | #define ECRYPT_CONFIG 7 | 8 | /* ------------------------------------------------------------------------- */ 9 | 10 | /* Guess the endianness of the target architecture. */ 11 | 12 | /* 13 | * The LITTLE endian machines: 14 | */ 15 | #if defined(__ultrix) /* Older MIPS */ 16 | #define ECRYPT_LITTLE_ENDIAN 17 | #elif defined(__alpha) /* Alpha */ 18 | #define ECRYPT_LITTLE_ENDIAN 19 | #elif defined(i386) /* x86 (gcc) */ 20 | #define ECRYPT_LITTLE_ENDIAN 21 | #elif defined(__i386) /* x86 (gcc) */ 22 | #define ECRYPT_LITTLE_ENDIAN 23 | #elif defined(__x86_64) /* x86_64 (gcc) */ 24 | #define ECRYPT_LITTLE_ENDIAN 25 | #elif defined(_M_IX86) /* x86 (MSC, Borland) */ 26 | #define ECRYPT_LITTLE_ENDIAN 27 | #elif defined(_MSC_VER) /* x86 (surely MSC) */ 28 | #define ECRYPT_LITTLE_ENDIAN 29 | #elif defined(__INTEL_COMPILER) /* x86 (surely Intel compiler icl.exe) */ 30 | #define ECRYPT_LITTLE_ENDIAN 31 | 32 | /* 33 | * The BIG endian machines: 34 | */ 35 | #elif defined(__sparc) /* Newer Sparc's */ 36 | #define ECRYPT_BIG_ENDIAN 37 | #elif defined(__powerpc__) /* PowerPC */ 38 | #define ECRYPT_BIG_ENDIAN 39 | #elif defined(__ppc__) /* PowerPC */ 40 | #define ECRYPT_BIG_ENDIAN 41 | #elif defined(__hppa) /* HP-PA */ 42 | #define ECRYPT_BIG_ENDIAN 43 | 44 | /* 45 | * Finally machines with UNKNOWN endianness: 46 | */ 47 | #elif defined (_AIX) /* RS6000 */ 48 | #define ECRYPT_UNKNOWN 49 | #elif defined(__aux) /* 68K */ 50 | #define ECRYPT_UNKNOWN 51 | #elif defined(__dgux) /* 88K (but P6 in latest boxes) */ 52 | #define ECRYPT_UNKNOWN 53 | #elif defined(__sgi) /* Newer MIPS */ 54 | #define ECRYPT_UNKNOWN 55 | #else /* Any other processor */ 56 | #define ECRYPT_UNKNOWN 57 | #endif 58 | 59 | /* ------------------------------------------------------------------------- */ 60 | 61 | /* 62 | * Find minimal-width types to store 8-bit, 16-bit, 32-bit, and 64-bit 63 | * integers. 64 | * 65 | * Note: to enable 64-bit types on 32-bit compilers, it might be 66 | * necessary to switch from ISO C90 mode to ISO C99 mode (e.g., gcc 67 | * -std=c99), or to allow compiler-specific extensions. 68 | */ 69 | 70 | #include 71 | 72 | /* --- check char --- */ 73 | 74 | #if (UCHAR_MAX / 0xFU > 0xFU) 75 | #ifndef I8T 76 | #define I8T char 77 | #define U8C(v) (v##U) 78 | 79 | #if (UCHAR_MAX == 0xFFU) 80 | #define ECRYPT_I8T_IS_BYTE 81 | #endif 82 | 83 | #endif 84 | 85 | #if (UCHAR_MAX / 0xFFU > 0xFFU) 86 | #ifndef I16T 87 | #define I16T char 88 | #define U16C(v) (v##U) 89 | #endif 90 | 91 | #if (UCHAR_MAX / 0xFFFFU > 0xFFFFU) 92 | #ifndef I32T 93 | #define I32T char 94 | #define U32C(v) (v##U) 95 | #endif 96 | 97 | #if (UCHAR_MAX / 0xFFFFFFFFU > 0xFFFFFFFFU) 98 | #ifndef I64T 99 | #define I64T char 100 | #define U64C(v) (v##U) 101 | #define ECRYPT_NATIVE64 102 | #endif 103 | 104 | #endif 105 | #endif 106 | #endif 107 | #endif 108 | 109 | /* --- check short --- */ 110 | 111 | #if (USHRT_MAX / 0xFU > 0xFU) 112 | #ifndef I8T 113 | #define I8T short 114 | #define U8C(v) (v##U) 115 | 116 | #if (USHRT_MAX == 0xFFU) 117 | #define ECRYPT_I8T_IS_BYTE 118 | #endif 119 | 120 | #endif 121 | 122 | #if (USHRT_MAX / 0xFFU > 0xFFU) 123 | #ifndef I16T 124 | #define I16T short 125 | #define U16C(v) (v##U) 126 | #endif 127 | 128 | #if (USHRT_MAX / 0xFFFFU > 0xFFFFU) 129 | #ifndef I32T 130 | #define I32T short 131 | #define U32C(v) (v##U) 132 | #endif 133 | 134 | #if (USHRT_MAX / 0xFFFFFFFFU > 0xFFFFFFFFU) 135 | #ifndef I64T 136 | #define I64T short 137 | #define U64C(v) (v##U) 138 | #define ECRYPT_NATIVE64 139 | #endif 140 | 141 | #endif 142 | #endif 143 | #endif 144 | #endif 145 | 146 | /* --- check int --- */ 147 | 148 | #if (UINT_MAX / 0xFU > 0xFU) 149 | #ifndef I8T 150 | #define I8T int 151 | #define U8C(v) (v##U) 152 | 153 | #if (ULONG_MAX == 0xFFU) 154 | #define ECRYPT_I8T_IS_BYTE 155 | #endif 156 | 157 | #endif 158 | 159 | #if (UINT_MAX / 0xFFU > 0xFFU) 160 | #ifndef I16T 161 | #define I16T int 162 | #define U16C(v) (v##U) 163 | #endif 164 | 165 | #if (UINT_MAX / 0xFFFFU > 0xFFFFU) 166 | #ifndef I32T 167 | #define I32T int 168 | #define U32C(v) (v##U) 169 | #endif 170 | 171 | #if (UINT_MAX / 0xFFFFFFFFU > 0xFFFFFFFFU) 172 | #ifndef I64T 173 | #define I64T int 174 | #define U64C(v) (v##U) 175 | #define ECRYPT_NATIVE64 176 | #endif 177 | 178 | #endif 179 | #endif 180 | #endif 181 | #endif 182 | 183 | /* --- check long --- */ 184 | 185 | #if (ULONG_MAX / 0xFUL > 0xFUL) 186 | #ifndef I8T 187 | #define I8T long 188 | #define U8C(v) (v##UL) 189 | 190 | #if (ULONG_MAX == 0xFFUL) 191 | #define ECRYPT_I8T_IS_BYTE 192 | #endif 193 | 194 | #endif 195 | 196 | #if (ULONG_MAX / 0xFFUL > 0xFFUL) 197 | #ifndef I16T 198 | #define I16T long 199 | #define U16C(v) (v##UL) 200 | #endif 201 | 202 | #if (ULONG_MAX / 0xFFFFUL > 0xFFFFUL) 203 | #ifndef I32T 204 | #define I32T long 205 | #define U32C(v) (v##UL) 206 | #endif 207 | 208 | #if (ULONG_MAX / 0xFFFFFFFFUL > 0xFFFFFFFFUL) 209 | #ifndef I64T 210 | #define I64T long 211 | #define U64C(v) (v##UL) 212 | #define ECRYPT_NATIVE64 213 | #endif 214 | 215 | #endif 216 | #endif 217 | #endif 218 | #endif 219 | 220 | /* --- check long long --- */ 221 | 222 | #ifdef ULLONG_MAX 223 | 224 | #if (ULLONG_MAX / 0xFULL > 0xFULL) 225 | #ifndef I8T 226 | #define I8T long long 227 | #define U8C(v) (v##ULL) 228 | 229 | #if (ULLONG_MAX == 0xFFULL) 230 | #define ECRYPT_I8T_IS_BYTE 231 | #endif 232 | 233 | #endif 234 | 235 | #if (ULLONG_MAX / 0xFFULL > 0xFFULL) 236 | #ifndef I16T 237 | #define I16T long long 238 | #define U16C(v) (v##ULL) 239 | #endif 240 | 241 | #if (ULLONG_MAX / 0xFFFFULL > 0xFFFFULL) 242 | #ifndef I32T 243 | #define I32T long long 244 | #define U32C(v) (v##ULL) 245 | #endif 246 | 247 | #if (ULLONG_MAX / 0xFFFFFFFFULL > 0xFFFFFFFFULL) 248 | #ifndef I64T 249 | #define I64T long long 250 | #define U64C(v) (v##ULL) 251 | #endif 252 | 253 | #endif 254 | #endif 255 | #endif 256 | #endif 257 | 258 | #endif 259 | 260 | /* --- check __int64 --- */ 261 | 262 | #if !defined(__STDC__) && defined(_UI64_MAX) 263 | 264 | #ifndef I64T 265 | #define I64T __int64 266 | #define U64C(v) (v##ui64) 267 | #endif 268 | 269 | #endif 270 | 271 | /* --- if platform doesn't announce anything, use most common choices --- */ 272 | 273 | #ifndef I8T 274 | #define I8T char 275 | #define U8C(v) (v##U) 276 | #endif 277 | #ifndef I16T 278 | #define I16T short 279 | #define U16C(v) (v##U) 280 | #endif 281 | #ifndef I32T 282 | #define I32T int 283 | #define U32C(v) (v##U) 284 | #endif 285 | #ifndef I64T 286 | #define I64T long long 287 | #define U64C(v) (v##ULL) 288 | #endif 289 | 290 | /* ------------------------------------------------------------------------- */ 291 | 292 | /* find the largest type on this platform (used for alignment) */ 293 | 294 | #if defined(__SSE__) || (defined(_MSC_VER) && (_MSC_VER >= 1300)) 295 | 296 | #include 297 | #define MAXT __m128 298 | 299 | #elif defined(__MMX__) 300 | 301 | #include 302 | #define MAXT __m64 303 | 304 | #elif defined(__ALTIVEC__) 305 | 306 | #define MAXT __vector int 307 | 308 | #else 309 | 310 | #define MAXT long 311 | 312 | #endif 313 | 314 | /* ------------------------------------------------------------------------- */ 315 | 316 | #endif 317 | -------------------------------------------------------------------------------- /ecrypt-machine.h: -------------------------------------------------------------------------------- 1 | /* ecrypt-machine.h */ 2 | 3 | /* 4 | * This file is included by 'ecrypt-portable.h'. It allows to override 5 | * the default macros for specific platforms. Please carefully check 6 | * the machine code generated by your compiler (with optimisations 7 | * turned on) before deciding to edit this file. 8 | */ 9 | 10 | /* ------------------------------------------------------------------------- */ 11 | 12 | #if (defined(ECRYPT_DEFAULT_ROT) && !defined(ECRYPT_MACHINE_ROT)) 13 | 14 | #define ECRYPT_MACHINE_ROT 15 | 16 | #if (defined(WIN32) && defined(_MSC_VER)) 17 | 18 | #undef ROTL32 19 | #undef ROTR32 20 | #undef ROTL64 21 | #undef ROTR64 22 | 23 | #include 24 | 25 | #pragma intrinsic(_lrotl) /* compile rotations "inline" */ 26 | #pragma intrinsic(_lrotr) 27 | 28 | #define ROTL32(v, n) _lrotl(v, n) 29 | #define ROTR32(v, n) _lrotr(v, n) 30 | #define ROTL64(v, n) _rotl64(v, n) 31 | #define ROTR64(v, n) _rotr64(v, n) 32 | 33 | #endif 34 | 35 | #endif 36 | 37 | /* ------------------------------------------------------------------------- */ 38 | 39 | #if (defined(ECRYPT_DEFAULT_SWAP) && !defined(ECRYPT_MACHINE_SWAP)) 40 | 41 | #define ECRYPT_MACHINE_SWAP 42 | 43 | /* 44 | * If you want to overwrite the default swap macros, put it here. And so on. 45 | */ 46 | 47 | #endif 48 | 49 | /* ------------------------------------------------------------------------- */ 50 | -------------------------------------------------------------------------------- /ecrypt-portable.h: -------------------------------------------------------------------------------- 1 | /* ecrypt-portable.h */ 2 | 3 | /* 4 | * WARNING: the conversions defined below are implemented as macros, 5 | * and should be used carefully. They should NOT be used with 6 | * parameters which perform some action. E.g., the following two lines 7 | * are not equivalent: 8 | * 9 | * 1) ++x; y = ROTL32(x, n); 10 | * 2) y = ROTL32(++x, n); 11 | */ 12 | 13 | /* 14 | * *** Please do not edit this file. *** 15 | * 16 | * The default macros can be overridden for specific architectures by 17 | * editing 'ecrypt-machine.h'. 18 | */ 19 | 20 | #ifndef ECRYPT_PORTABLE 21 | #define ECRYPT_PORTABLE 22 | 23 | #include "ecrypt-config.h" 24 | 25 | /* ------------------------------------------------------------------------- */ 26 | 27 | /* 28 | * The following types are defined (if available): 29 | * 30 | * u8: unsigned integer type, at least 8 bits 31 | * u16: unsigned integer type, at least 16 bits 32 | * u32: unsigned integer type, at least 32 bits 33 | * u64: unsigned integer type, at least 64 bits 34 | * 35 | * s8, s16, s32, s64 -> signed counterparts of u8, u16, u32, u64 36 | * 37 | * The selection of minimum-width integer types is taken care of by 38 | * 'ecrypt-config.h'. Note: to enable 64-bit types on 32-bit 39 | * compilers, it might be necessary to switch from ISO C90 mode to ISO 40 | * C99 mode (e.g., gcc -std=c99). 41 | */ 42 | 43 | #ifdef I8T 44 | typedef signed I8T s8; 45 | typedef unsigned I8T u8; 46 | #endif 47 | 48 | #ifdef I16T 49 | typedef signed I16T s16; 50 | typedef unsigned I16T u16; 51 | #endif 52 | 53 | #ifdef I32T 54 | typedef signed I32T s32; 55 | typedef unsigned I32T u32; 56 | #endif 57 | 58 | #ifdef I64T 59 | typedef signed I64T s64; 60 | typedef unsigned I64T u64; 61 | #endif 62 | 63 | /* 64 | * The following macros are used to obtain exact-width results. 65 | */ 66 | 67 | #define U8V(v) ((u8)(v) & U8C(0xFF)) 68 | #define U16V(v) ((u16)(v) & U16C(0xFFFF)) 69 | #define U32V(v) ((u32)(v) & U32C(0xFFFFFFFF)) 70 | #define U64V(v) ((u64)(v) & U64C(0xFFFFFFFFFFFFFFFF)) 71 | 72 | /* ------------------------------------------------------------------------- */ 73 | 74 | /* 75 | * The following macros return words with their bits rotated over n 76 | * positions to the left/right. 77 | */ 78 | 79 | #define ECRYPT_DEFAULT_ROT 80 | 81 | #define ROTL8(v, n) \ 82 | (U8V((v) << (n)) | ((v) >> (8 - (n)))) 83 | 84 | #define ROTL16(v, n) \ 85 | (U16V((v) << (n)) | ((v) >> (16 - (n)))) 86 | 87 | #define ROTL32(v, n) \ 88 | (U32V((v) << (n)) | ((v) >> (32 - (n)))) 89 | 90 | #define ROTL64(v, n) \ 91 | (U64V((v) << (n)) | ((v) >> (64 - (n)))) 92 | 93 | #define ROTR8(v, n) ROTL8(v, 8 - (n)) 94 | #define ROTR16(v, n) ROTL16(v, 16 - (n)) 95 | #define ROTR32(v, n) ROTL32(v, 32 - (n)) 96 | #define ROTR64(v, n) ROTL64(v, 64 - (n)) 97 | 98 | #include "ecrypt-machine.h" 99 | 100 | /* ------------------------------------------------------------------------- */ 101 | 102 | /* 103 | * The following macros return a word with bytes in reverse order. 104 | */ 105 | 106 | #define ECRYPT_DEFAULT_SWAP 107 | 108 | #define SWAP16(v) \ 109 | ROTL16(v, 8) 110 | 111 | #define SWAP32(v) \ 112 | ((ROTL32(v, 8) & U32C(0x00FF00FF)) | \ 113 | (ROTL32(v, 24) & U32C(0xFF00FF00))) 114 | 115 | #ifdef ECRYPT_NATIVE64 116 | #define SWAP64(v) \ 117 | ((ROTL64(v, 8) & U64C(0x000000FF000000FF)) | \ 118 | (ROTL64(v, 24) & U64C(0x0000FF000000FF00)) | \ 119 | (ROTL64(v, 40) & U64C(0x00FF000000FF0000)) | \ 120 | (ROTL64(v, 56) & U64C(0xFF000000FF000000))) 121 | #else 122 | #define SWAP64(v) \ 123 | (((u64)SWAP32(U32V(v)) << 32) | (u64)SWAP32(U32V(v >> 32))) 124 | #endif 125 | 126 | #include "ecrypt-machine.h" 127 | 128 | #define ECRYPT_DEFAULT_WTOW 129 | 130 | #ifdef ECRYPT_LITTLE_ENDIAN 131 | #define U16TO16_LITTLE(v) (v) 132 | #define U32TO32_LITTLE(v) (v) 133 | #define U64TO64_LITTLE(v) (v) 134 | 135 | #define U16TO16_BIG(v) SWAP16(v) 136 | #define U32TO32_BIG(v) SWAP32(v) 137 | #define U64TO64_BIG(v) SWAP64(v) 138 | #endif 139 | 140 | #ifdef ECRYPT_BIG_ENDIAN 141 | #define U16TO16_LITTLE(v) SWAP16(v) 142 | #define U32TO32_LITTLE(v) SWAP32(v) 143 | #define U64TO64_LITTLE(v) SWAP64(v) 144 | 145 | #define U16TO16_BIG(v) (v) 146 | #define U32TO32_BIG(v) (v) 147 | #define U64TO64_BIG(v) (v) 148 | #endif 149 | 150 | #include "ecrypt-machine.h" 151 | 152 | /* 153 | * The following macros load words from an array of bytes with 154 | * different types of endianness, and vice versa. 155 | */ 156 | 157 | #define ECRYPT_DEFAULT_BTOW 158 | 159 | #if (!defined(ECRYPT_UNKNOWN) && defined(ECRYPT_I8T_IS_BYTE)) 160 | 161 | #define U8TO16_LITTLE(p) U16TO16_LITTLE(((u16*)(p))[0]) 162 | #define U8TO32_LITTLE(p) U32TO32_LITTLE(((u32*)(p))[0]) 163 | #define U8TO64_LITTLE(p) U64TO64_LITTLE(((u64*)(p))[0]) 164 | 165 | #define U8TO16_BIG(p) U16TO16_BIG(((u16*)(p))[0]) 166 | #define U8TO32_BIG(p) U32TO32_BIG(((u32*)(p))[0]) 167 | #define U8TO64_BIG(p) U64TO64_BIG(((u64*)(p))[0]) 168 | 169 | #define U16TO8_LITTLE(p, v) (((u16*)(p))[0] = U16TO16_LITTLE(v)) 170 | #define U32TO8_LITTLE(p, v) (((u32*)(p))[0] = U32TO32_LITTLE(v)) 171 | #define U64TO8_LITTLE(p, v) (((u64*)(p))[0] = U64TO64_LITTLE(v)) 172 | 173 | #define U16TO8_BIG(p, v) (((u16*)(p))[0] = U16TO16_BIG(v)) 174 | #define U32TO8_BIG(p, v) (((u32*)(p))[0] = U32TO32_BIG(v)) 175 | #define U64TO8_BIG(p, v) (((u64*)(p))[0] = U64TO64_BIG(v)) 176 | 177 | #else 178 | 179 | #define U8TO16_LITTLE(p) \ 180 | (((u16)((p)[0]) ) | \ 181 | ((u16)((p)[1]) << 8)) 182 | 183 | #define U8TO32_LITTLE(p) \ 184 | (((u32)((p)[0]) ) | \ 185 | ((u32)((p)[1]) << 8) | \ 186 | ((u32)((p)[2]) << 16) | \ 187 | ((u32)((p)[3]) << 24)) 188 | 189 | #ifdef ECRYPT_NATIVE64 190 | #define U8TO64_LITTLE(p) \ 191 | (((u64)((p)[0]) ) | \ 192 | ((u64)((p)[1]) << 8) | \ 193 | ((u64)((p)[2]) << 16) | \ 194 | ((u64)((p)[3]) << 24) | \ 195 | ((u64)((p)[4]) << 32) | \ 196 | ((u64)((p)[5]) << 40) | \ 197 | ((u64)((p)[6]) << 48) | \ 198 | ((u64)((p)[7]) << 56)) 199 | #else 200 | #define U8TO64_LITTLE(p) \ 201 | ((u64)U8TO32_LITTLE(p) | ((u64)U8TO32_LITTLE((p) + 4) << 32)) 202 | #endif 203 | 204 | #define U8TO16_BIG(p) \ 205 | (((u16)((p)[0]) << 8) | \ 206 | ((u16)((p)[1]) )) 207 | 208 | #define U8TO32_BIG(p) \ 209 | (((u32)((p)[0]) << 24) | \ 210 | ((u32)((p)[1]) << 16) | \ 211 | ((u32)((p)[2]) << 8) | \ 212 | ((u32)((p)[3]) )) 213 | 214 | #ifdef ECRYPT_NATIVE64 215 | #define U8TO64_BIG(p) \ 216 | (((u64)((p)[0]) << 56) | \ 217 | ((u64)((p)[1]) << 48) | \ 218 | ((u64)((p)[2]) << 40) | \ 219 | ((u64)((p)[3]) << 32) | \ 220 | ((u64)((p)[4]) << 24) | \ 221 | ((u64)((p)[5]) << 16) | \ 222 | ((u64)((p)[6]) << 8) | \ 223 | ((u64)((p)[7]) )) 224 | #else 225 | #define U8TO64_BIG(p) \ 226 | (((u64)U8TO32_BIG(p) << 32) | (u64)U8TO32_BIG((p) + 4)) 227 | #endif 228 | 229 | #define U16TO8_LITTLE(p, v) \ 230 | do { \ 231 | (p)[0] = U8V((v) ); \ 232 | (p)[1] = U8V((v) >> 8); \ 233 | } while (0) 234 | 235 | #define U32TO8_LITTLE(p, v) \ 236 | do { \ 237 | (p)[0] = U8V((v) ); \ 238 | (p)[1] = U8V((v) >> 8); \ 239 | (p)[2] = U8V((v) >> 16); \ 240 | (p)[3] = U8V((v) >> 24); \ 241 | } while (0) 242 | 243 | #ifdef ECRYPT_NATIVE64 244 | #define U64TO8_LITTLE(p, v) \ 245 | do { \ 246 | (p)[0] = U8V((v) ); \ 247 | (p)[1] = U8V((v) >> 8); \ 248 | (p)[2] = U8V((v) >> 16); \ 249 | (p)[3] = U8V((v) >> 24); \ 250 | (p)[4] = U8V((v) >> 32); \ 251 | (p)[5] = U8V((v) >> 40); \ 252 | (p)[6] = U8V((v) >> 48); \ 253 | (p)[7] = U8V((v) >> 56); \ 254 | } while (0) 255 | #else 256 | #define U64TO8_LITTLE(p, v) \ 257 | do { \ 258 | U32TO8_LITTLE((p), U32V((v) )); \ 259 | U32TO8_LITTLE((p) + 4, U32V((v) >> 32)); \ 260 | } while (0) 261 | #endif 262 | 263 | #define U16TO8_BIG(p, v) \ 264 | do { \ 265 | (p)[0] = U8V((v) ); \ 266 | (p)[1] = U8V((v) >> 8); \ 267 | } while (0) 268 | 269 | #define U32TO8_BIG(p, v) \ 270 | do { \ 271 | (p)[0] = U8V((v) >> 24); \ 272 | (p)[1] = U8V((v) >> 16); \ 273 | (p)[2] = U8V((v) >> 8); \ 274 | (p)[3] = U8V((v) ); \ 275 | } while (0) 276 | 277 | #ifdef ECRYPT_NATIVE64 278 | #define U64TO8_BIG(p, v) \ 279 | do { \ 280 | (p)[0] = U8V((v) >> 56); \ 281 | (p)[1] = U8V((v) >> 48); \ 282 | (p)[2] = U8V((v) >> 40); \ 283 | (p)[3] = U8V((v) >> 32); \ 284 | (p)[4] = U8V((v) >> 24); \ 285 | (p)[5] = U8V((v) >> 16); \ 286 | (p)[6] = U8V((v) >> 8); \ 287 | (p)[7] = U8V((v) ); \ 288 | } while (0) 289 | #else 290 | #define U64TO8_BIG(p, v) \ 291 | do { \ 292 | U32TO8_BIG((p), U32V((v) >> 32)); \ 293 | U32TO8_BIG((p) + 4, U32V((v) )); \ 294 | } while (0) 295 | #endif 296 | 297 | #endif 298 | 299 | #include "ecrypt-machine.h" 300 | 301 | /* ------------------------------------------------------------------------- */ 302 | 303 | #define AT_LEAST_ONE(n) (((n) < 1) ? 1 : (n)) 304 | 305 | #define ALIGN(t, v, n) \ 306 | union { t b[n]; MAXT l[AT_LEAST_ONE(n * sizeof(t) / sizeof(MAXT))]; } v 307 | 308 | /* ------------------------------------------------------------------------- */ 309 | 310 | #endif 311 | -------------------------------------------------------------------------------- /ecrypt-sync.h: -------------------------------------------------------------------------------- 1 | #define ECRYPT_VARIANT 1 2 | #define ECRYPT_API 3 | /* ecrypt-sync.h */ 4 | 5 | /* 6 | * Header file for synchronous stream ciphers without authentication 7 | * mechanism. 8 | * 9 | * *** Please only edit parts marked with "[edit]". *** 10 | */ 11 | 12 | #ifndef ECRYPT_SYNC 13 | #define ECRYPT_SYNC 14 | 15 | #include "ecrypt-portable.h" 16 | 17 | /* ------------------------------------------------------------------------- */ 18 | 19 | /* Cipher parameters */ 20 | 21 | /* 22 | * The name of your cipher. 23 | */ 24 | #define ECRYPT_NAME "ChaCha20" 25 | #define ECRYPT_PROFILE "_____" 26 | 27 | /* 28 | * Specify which key and IV sizes are supported by your cipher. A user 29 | * should be able to enumerate the supported sizes by running the 30 | * following code: 31 | * 32 | * for (i = 0; ECRYPT_KEYSIZE(i) <= ECRYPT_MAXKEYSIZE; ++i) 33 | * { 34 | * keysize = ECRYPT_KEYSIZE(i); 35 | * 36 | * ... 37 | * } 38 | * 39 | * All sizes are in bits. 40 | */ 41 | 42 | #define ECRYPT_MAXKEYSIZE 256 /* [edit] */ 43 | #define ECRYPT_KEYSIZE(i) (128 + (i)*128) /* [edit] */ 44 | 45 | #define ECRYPT_MAXIVSIZE 64 /* [edit] */ 46 | #define ECRYPT_IVSIZE(i) (64 + (i)*64) /* [edit] */ 47 | 48 | /* ------------------------------------------------------------------------- */ 49 | 50 | /* Data structures */ 51 | 52 | /* 53 | * ECRYPT_ctx is the structure containing the representation of the 54 | * internal state of your cipher. 55 | */ 56 | 57 | typedef struct 58 | { 59 | u32 input[16]; /* could be compressed */ 60 | /* 61 | * [edit] 62 | * 63 | * Put here all state variable needed during the encryption process. 64 | */ 65 | } ECRYPT_ctx; 66 | 67 | /* ------------------------------------------------------------------------- */ 68 | 69 | /* Mandatory functions */ 70 | 71 | /* 72 | * Key and message independent initialization. This function will be 73 | * called once when the program starts (e.g., to build expanded S-box 74 | * tables). 75 | */ 76 | void ECRYPT_init(); 77 | 78 | /* 79 | * Key setup. It is the user's responsibility to select the values of 80 | * keysize and ivsize from the set of supported values specified 81 | * above. 82 | */ 83 | void ECRYPT_keysetup( 84 | ECRYPT_ctx* ctx, 85 | const u8* key, 86 | u32 keysize, /* Key size in bits. */ 87 | u32 ivsize); /* IV size in bits. */ 88 | 89 | /* 90 | * IV setup. After having called ECRYPT_keysetup(), the user is 91 | * allowed to call ECRYPT_ivsetup() different times in order to 92 | * encrypt/decrypt different messages with the same key but different 93 | * IV's. 94 | */ 95 | void ECRYPT_ivsetup( 96 | ECRYPT_ctx* ctx, 97 | const u8* iv); 98 | 99 | /* 100 | * Encryption/decryption of arbitrary length messages. 101 | * 102 | * For efficiency reasons, the API provides two types of 103 | * encrypt/decrypt functions. The ECRYPT_encrypt_bytes() function 104 | * (declared here) encrypts byte strings of arbitrary length, while 105 | * the ECRYPT_encrypt_blocks() function (defined later) only accepts 106 | * lengths which are multiples of ECRYPT_BLOCKLENGTH. 107 | * 108 | * The user is allowed to make multiple calls to 109 | * ECRYPT_encrypt_blocks() to incrementally encrypt a long message, 110 | * but he is NOT allowed to make additional encryption calls once he 111 | * has called ECRYPT_encrypt_bytes() (unless he starts a new message 112 | * of course). For example, this sequence of calls is acceptable: 113 | * 114 | * ECRYPT_keysetup(); 115 | * 116 | * ECRYPT_ivsetup(); 117 | * ECRYPT_encrypt_blocks(); 118 | * ECRYPT_encrypt_blocks(); 119 | * ECRYPT_encrypt_bytes(); 120 | * 121 | * ECRYPT_ivsetup(); 122 | * ECRYPT_encrypt_blocks(); 123 | * ECRYPT_encrypt_blocks(); 124 | * 125 | * ECRYPT_ivsetup(); 126 | * ECRYPT_encrypt_bytes(); 127 | * 128 | * The following sequence is not: 129 | * 130 | * ECRYPT_keysetup(); 131 | * ECRYPT_ivsetup(); 132 | * ECRYPT_encrypt_blocks(); 133 | * ECRYPT_encrypt_bytes(); 134 | * ECRYPT_encrypt_blocks(); 135 | */ 136 | 137 | void ECRYPT_encrypt_bytes( 138 | ECRYPT_ctx* ctx, 139 | const u8* plaintext, 140 | u8* ciphertext, 141 | u32 msglen); /* Message length in bytes. */ 142 | 143 | void ECRYPT_decrypt_bytes( 144 | ECRYPT_ctx* ctx, 145 | const u8* ciphertext, 146 | u8* plaintext, 147 | u32 msglen); /* Message length in bytes. */ 148 | 149 | /* ------------------------------------------------------------------------- */ 150 | 151 | /* Optional features */ 152 | 153 | /* 154 | * For testing purposes it can sometimes be useful to have a function 155 | * which immediately generates keystream without having to provide it 156 | * with a zero plaintext. If your cipher cannot provide this function 157 | * (e.g., because it is not strictly a synchronous cipher), please 158 | * reset the ECRYPT_GENERATES_KEYSTREAM flag. 159 | */ 160 | 161 | #define ECRYPT_GENERATES_KEYSTREAM 162 | #ifdef ECRYPT_GENERATES_KEYSTREAM 163 | 164 | void ECRYPT_keystream_bytes( 165 | ECRYPT_ctx* ctx, 166 | u8* keystream, 167 | u32 length); /* Length of keystream in bytes. */ 168 | 169 | #endif 170 | 171 | /* ------------------------------------------------------------------------- */ 172 | 173 | /* Optional optimizations */ 174 | 175 | /* 176 | * By default, the functions in this section are implemented using 177 | * calls to functions declared above. However, you might want to 178 | * implement them differently for performance reasons. 179 | */ 180 | 181 | /* 182 | * All-in-one encryption/decryption of (short) packets. 183 | * 184 | * The default definitions of these functions can be found in 185 | * "ecrypt-sync.c". If you want to implement them differently, please 186 | * undef the ECRYPT_USES_DEFAULT_ALL_IN_ONE flag. 187 | */ 188 | #define ECRYPT_USES_DEFAULT_ALL_IN_ONE /* [edit] */ 189 | 190 | void ECRYPT_encrypt_packet( 191 | ECRYPT_ctx* ctx, 192 | const u8* iv, 193 | const u8* plaintext, 194 | u8* ciphertext, 195 | u32 msglen); 196 | 197 | void ECRYPT_decrypt_packet( 198 | ECRYPT_ctx* ctx, 199 | const u8* iv, 200 | const u8* ciphertext, 201 | u8* plaintext, 202 | u32 msglen); 203 | 204 | /* 205 | * Encryption/decryption of blocks. 206 | * 207 | * By default, these functions are defined as macros. If you want to 208 | * provide a different implementation, please undef the 209 | * ECRYPT_USES_DEFAULT_BLOCK_MACROS flag and implement the functions 210 | * declared below. 211 | */ 212 | 213 | #define ECRYPT_BLOCKLENGTH 64 /* [edit] */ 214 | 215 | #define ECRYPT_USES_DEFAULT_BLOCK_MACROS /* [edit] */ 216 | #ifdef ECRYPT_USES_DEFAULT_BLOCK_MACROS 217 | 218 | #define ECRYPT_encrypt_blocks(ctx, plaintext, ciphertext, blocks) \ 219 | ECRYPT_encrypt_bytes(ctx, plaintext, ciphertext, \ 220 | (blocks) * ECRYPT_BLOCKLENGTH) 221 | 222 | #define ECRYPT_decrypt_blocks(ctx, ciphertext, plaintext, blocks) \ 223 | ECRYPT_decrypt_bytes(ctx, ciphertext, plaintext, \ 224 | (blocks) * ECRYPT_BLOCKLENGTH) 225 | 226 | #ifdef ECRYPT_GENERATES_KEYSTREAM 227 | 228 | #define ECRYPT_keystream_blocks(ctx, keystream, blocks) \ 229 | ECRYPT_keystream_bytes(ctx, keystream, \ 230 | (blocks) * ECRYPT_BLOCKLENGTH) 231 | 232 | #endif 233 | 234 | #else 235 | 236 | void ECRYPT_encrypt_blocks( 237 | ECRYPT_ctx* ctx, 238 | const u8* plaintext, 239 | u8* ciphertext, 240 | u32 blocks); /* Message length in blocks. */ 241 | 242 | void ECRYPT_decrypt_blocks( 243 | ECRYPT_ctx* ctx, 244 | const u8* ciphertext, 245 | u8* plaintext, 246 | u32 blocks); /* Message length in blocks. */ 247 | 248 | #ifdef ECRYPT_GENERATES_KEYSTREAM 249 | 250 | void ECRYPT_keystream_blocks( 251 | ECRYPT_ctx* ctx, 252 | const u8* keystream, 253 | u32 blocks); /* Keystream length in blocks. */ 254 | 255 | #endif 256 | 257 | #endif 258 | 259 | /* 260 | * If your cipher can be implemented in different ways, you can use 261 | * the ECRYPT_VARIANT parameter to allow the user to choose between 262 | * them at compile time (e.g., gcc -DECRYPT_VARIANT=3 ...). Please 263 | * only use this possibility if you really think it could make a 264 | * significant difference and keep the number of variants 265 | * (ECRYPT_MAXVARIANT) as small as possible (definitely not more than 266 | * 10). Note also that all variants should have exactly the same 267 | * external interface (i.e., the same ECRYPT_BLOCKLENGTH, etc.). 268 | */ 269 | #define ECRYPT_MAXVARIANT 1 /* [edit] */ 270 | 271 | #ifndef ECRYPT_VARIANT 272 | #define ECRYPT_VARIANT 1 273 | #endif 274 | 275 | #if (ECRYPT_VARIANT > ECRYPT_MAXVARIANT) 276 | #error this variant does not exist 277 | #endif 278 | 279 | /* ------------------------------------------------------------------------- */ 280 | 281 | #endif 282 | -------------------------------------------------------------------------------- /poly1305-donna-16.h: -------------------------------------------------------------------------------- 1 | /* 2 | poly1305 implementation using 16 bit * 16 bit = 32 bit multiplication and 32 bit addition 3 | */ 4 | 5 | #if defined(_MSC_VER) 6 | #define POLY1305_NOINLINE __declspec(noinline) 7 | #elif defined(__GNUC__) 8 | #define POLY1305_NOINLINE __attribute__((noinline)) 9 | #else 10 | #define POLY1305_NOINLINE 11 | #endif 12 | 13 | #define poly1305_block_size 16 14 | 15 | /* 17 + sizeof(size_t) + 18*sizeof(unsigned short) */ 16 | typedef struct poly1305_state_internal_t { 17 | unsigned char buffer[poly1305_block_size]; 18 | size_t leftover; 19 | unsigned short r[10]; 20 | unsigned short h[10]; 21 | unsigned short pad[8]; 22 | unsigned char final; 23 | } poly1305_state_internal_t; 24 | 25 | /* interpret two 8 bit unsigned integers as a 16 bit unsigned integer in little endian */ 26 | static unsigned short 27 | U8TO16(const unsigned char *p) { 28 | return 29 | (((unsigned short)(p[0] & 0xff) ) | 30 | ((unsigned short)(p[1] & 0xff) << 8)); 31 | } 32 | 33 | /* store a 16 bit unsigned integer as two 8 bit unsigned integers in little endian */ 34 | static void 35 | U16TO8(unsigned char *p, unsigned short v) { 36 | p[0] = (v ) & 0xff; 37 | p[1] = (v >> 8) & 0xff; 38 | } 39 | 40 | void 41 | poly1305_init(poly1305_context *ctx, const unsigned char key[32]) { 42 | poly1305_state_internal_t *st = (poly1305_state_internal_t *)ctx; 43 | unsigned short t0,t1,t2,t3,t4,t5,t6,t7; 44 | size_t i; 45 | 46 | /* r &= 0xffffffc0ffffffc0ffffffc0fffffff */ 47 | t0 = U8TO16(&key[ 0]); st->r[0] = ( t0 ) & 0x1fff; 48 | t1 = U8TO16(&key[ 2]); st->r[1] = ((t0 >> 13) | (t1 << 3)) & 0x1fff; 49 | t2 = U8TO16(&key[ 4]); st->r[2] = ((t1 >> 10) | (t2 << 6)) & 0x1f03; 50 | t3 = U8TO16(&key[ 6]); st->r[3] = ((t2 >> 7) | (t3 << 9)) & 0x1fff; 51 | t4 = U8TO16(&key[ 8]); st->r[4] = ((t3 >> 4) | (t4 << 12)) & 0x00ff; 52 | st->r[5] = ((t4 >> 1) ) & 0x1ffe; 53 | t5 = U8TO16(&key[10]); st->r[6] = ((t4 >> 14) | (t5 << 2)) & 0x1fff; 54 | t6 = U8TO16(&key[12]); st->r[7] = ((t5 >> 11) | (t6 << 5)) & 0x1f81; 55 | t7 = U8TO16(&key[14]); st->r[8] = ((t6 >> 8) | (t7 << 8)) & 0x1fff; 56 | st->r[9] = ((t7 >> 5) ) & 0x007f; 57 | 58 | /* h = 0 */ 59 | for (i = 0; i < 10; i++) 60 | st->h[i] = 0; 61 | 62 | /* save pad for later */ 63 | for (i = 0; i < 8; i++) 64 | st->pad[i] = U8TO16(&key[16 + (2 * i)]); 65 | 66 | st->leftover = 0; 67 | st->final = 0; 68 | } 69 | 70 | static void 71 | poly1305_blocks(poly1305_state_internal_t *st, const unsigned char *m, size_t bytes) { 72 | const unsigned short hibit = (st->final) ? 0 : (1 << 11); /* 1 << 128 */ 73 | unsigned short t0,t1,t2,t3,t4,t5,t6,t7; 74 | unsigned long d[10]; 75 | unsigned long c; 76 | 77 | while (bytes >= poly1305_block_size) { 78 | size_t i, j; 79 | 80 | /* h += m[i] */ 81 | t0 = U8TO16(&m[ 0]); st->h[0] += ( t0 ) & 0x1fff; 82 | t1 = U8TO16(&m[ 2]); st->h[1] += ((t0 >> 13) | (t1 << 3)) & 0x1fff; 83 | t2 = U8TO16(&m[ 4]); st->h[2] += ((t1 >> 10) | (t2 << 6)) & 0x1fff; 84 | t3 = U8TO16(&m[ 6]); st->h[3] += ((t2 >> 7) | (t3 << 9)) & 0x1fff; 85 | t4 = U8TO16(&m[ 8]); st->h[4] += ((t3 >> 4) | (t4 << 12)) & 0x1fff; 86 | st->h[5] += ((t4 >> 1) ) & 0x1fff; 87 | t5 = U8TO16(&m[10]); st->h[6] += ((t4 >> 14) | (t5 << 2)) & 0x1fff; 88 | t6 = U8TO16(&m[12]); st->h[7] += ((t5 >> 11) | (t6 << 5)) & 0x1fff; 89 | t7 = U8TO16(&m[14]); st->h[8] += ((t6 >> 8) | (t7 << 8)) & 0x1fff; 90 | st->h[9] += ((t7 >> 5) ) | hibit; 91 | 92 | /* h *= r, (partial) h %= p */ 93 | for (i = 0, c = 0; i < 10; i++) { 94 | d[i] = c; 95 | for (j = 0; j < 10; j++) { 96 | d[i] += (unsigned long)st->h[j] * ((j <= i) ? st->r[i - j] : (5 * st->r[i + 10 - j])); 97 | /* Sum(h[i] * r[i] * 5) will overflow slightly above 6 products with an unclamped r, so carry at 5 */ 98 | if (j == 4) { 99 | c = (d[i] >> 13); 100 | d[i] &= 0x1fff; 101 | } 102 | } 103 | c += (d[i] >> 13); 104 | d[i] &= 0x1fff; 105 | } 106 | c = ((c << 2) + c); /* c *= 5 */ 107 | c += d[0]; 108 | d[0] = ((unsigned short)c & 0x1fff); 109 | c = (c >> 13); 110 | d[1] += c; 111 | 112 | for (i = 0; i < 10; i++) 113 | st->h[i] = (unsigned short)d[i]; 114 | 115 | m += poly1305_block_size; 116 | bytes -= poly1305_block_size; 117 | } 118 | } 119 | 120 | POLY1305_NOINLINE void 121 | poly1305_finish(poly1305_context *ctx, unsigned char mac[16]) { 122 | poly1305_state_internal_t *st = (poly1305_state_internal_t *)ctx; 123 | unsigned short c; 124 | unsigned short g[10]; 125 | unsigned short mask; 126 | unsigned long f; 127 | size_t i; 128 | 129 | /* process the remaining block */ 130 | if (st->leftover) { 131 | size_t i = st->leftover; 132 | st->buffer[i++] = 1; 133 | for (; i < poly1305_block_size; i++) 134 | st->buffer[i] = 0; 135 | st->final = 1; 136 | poly1305_blocks(st, st->buffer, poly1305_block_size); 137 | } 138 | 139 | /* fully carry h */ 140 | c = st->h[1] >> 13; 141 | st->h[1] &= 0x1fff; 142 | for (i = 2; i < 10; i++) { 143 | st->h[i] += c; 144 | c = st->h[i] >> 13; 145 | st->h[i] &= 0x1fff; 146 | } 147 | st->h[0] += (c * 5); 148 | c = st->h[0] >> 13; 149 | st->h[0] &= 0x1fff; 150 | st->h[1] += c; 151 | c = st->h[1] >> 13; 152 | st->h[1] &= 0x1fff; 153 | st->h[2] += c; 154 | 155 | /* compute h + -p */ 156 | g[0] = st->h[0] + 5; 157 | c = g[0] >> 13; 158 | g[0] &= 0x1fff; 159 | for (i = 1; i < 10; i++) { 160 | g[i] = st->h[i] + c; 161 | c = g[i] >> 13; 162 | g[i] &= 0x1fff; 163 | } 164 | 165 | /* select h if h < p, or h + -p if h >= p */ 166 | mask = (c ^ 1) - 1; 167 | for (i = 0; i < 10; i++) 168 | g[i] &= mask; 169 | mask = ~mask; 170 | for (i = 0; i < 10; i++) 171 | st->h[i] = (st->h[i] & mask) | g[i]; 172 | 173 | /* h = h % (2^128) */ 174 | st->h[0] = ((st->h[0] ) | (st->h[1] << 13) ) & 0xffff; 175 | st->h[1] = ((st->h[1] >> 3) | (st->h[2] << 10) ) & 0xffff; 176 | st->h[2] = ((st->h[2] >> 6) | (st->h[3] << 7) ) & 0xffff; 177 | st->h[3] = ((st->h[3] >> 9) | (st->h[4] << 4) ) & 0xffff; 178 | st->h[4] = ((st->h[4] >> 12) | (st->h[5] << 1) | (st->h[6] << 14)) & 0xffff; 179 | st->h[5] = ((st->h[6] >> 2) | (st->h[7] << 11) ) & 0xffff; 180 | st->h[6] = ((st->h[7] >> 5) | (st->h[8] << 8) ) & 0xffff; 181 | st->h[7] = ((st->h[8] >> 8) | (st->h[9] << 5) ) & 0xffff; 182 | 183 | /* mac = (h + pad) % (2^128) */ 184 | f = (unsigned long)st->h[0] + st->pad[0]; 185 | st->h[0] = (unsigned short)f; 186 | for (i = 1; i < 8; i++) { 187 | f = (unsigned long)st->h[i] + st->pad[i] + (f >> 16); 188 | st->h[i] = (unsigned short)f; 189 | } 190 | 191 | for (i = 0; i < 8; i++) 192 | U16TO8(mac + (i * 2), st->h[i]); 193 | 194 | /* zero out the state */ 195 | for (i = 0; i < 10; i++) 196 | st->h[i] = 0; 197 | for (i = 0; i < 10; i++) 198 | st->r[i] = 0; 199 | for (i = 0; i < 8; i++) 200 | st->pad[i] = 0; 201 | } 202 | -------------------------------------------------------------------------------- /poly1305-donna.c: -------------------------------------------------------------------------------- 1 | #include "poly1305-donna.h" 2 | 3 | #if defined(POLY1305_8BIT) 4 | #include "poly1305-donna-8.h" 5 | #elif defined(POLY1305_16BIT) 6 | #include "poly1305-donna-16.h" 7 | #elif defined(POLY1305_32BIT) 8 | #include "poly1305-donna-32.h" 9 | #elif defined(POLY1305_64BIT) 10 | #include "poly1305-donna-64.h" 11 | #else 12 | 13 | /* auto detect between 32bit / 64bit */ 14 | #define HAS_SIZEOF_INT128_64BIT (defined(__SIZEOF_INT128__) && defined(__LP64__)) 15 | #define HAS_MSVC_64BIT (defined(_MSC_VER) && defined(_M_X64)) 16 | #define HAS_GCC_4_4_64BIT (defined(__GNUC__) && defined(__LP64__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 4)))) 17 | 18 | #if (HAS_SIZEOF_INT128_64BIT || HAS_MSVC_64BIT || HAS_GCC_4_4_64BIT) 19 | #include "poly1305-donna-64.h" 20 | #else 21 | #include "poly1305-donna-32.h" 22 | #endif 23 | 24 | #endif 25 | 26 | void 27 | poly1305_update(poly1305_context *ctx, const unsigned char *m, size_t bytes) { 28 | poly1305_state_internal_t *st = (poly1305_state_internal_t *)ctx; 29 | size_t i; 30 | 31 | /* handle leftover */ 32 | if (st->leftover) { 33 | size_t want = (poly1305_block_size - st->leftover); 34 | if (want > bytes) 35 | want = bytes; 36 | for (i = 0; i < want; i++) 37 | st->buffer[st->leftover + i] = m[i]; 38 | bytes -= want; 39 | m += want; 40 | st->leftover += want; 41 | if (st->leftover < poly1305_block_size) 42 | return; 43 | poly1305_blocks(st, st->buffer, poly1305_block_size); 44 | st->leftover = 0; 45 | } 46 | 47 | /* process full blocks */ 48 | if (bytes >= poly1305_block_size) { 49 | size_t want = (bytes & ~(poly1305_block_size - 1)); 50 | poly1305_blocks(st, m, want); 51 | m += want; 52 | bytes -= want; 53 | } 54 | 55 | /* store leftover */ 56 | if (bytes) { 57 | for (i = 0; i < bytes; i++) 58 | st->buffer[st->leftover + i] = m[i]; 59 | st->leftover += bytes; 60 | } 61 | } 62 | 63 | void 64 | poly1305_auth(unsigned char mac[16], const unsigned char *m, size_t bytes, const unsigned char key[32]) { 65 | poly1305_context ctx; 66 | poly1305_init(&ctx, key); 67 | poly1305_update(&ctx, m, bytes); 68 | poly1305_finish(&ctx, mac); 69 | } 70 | 71 | int 72 | poly1305_verify(const unsigned char mac1[16], const unsigned char mac2[16]) { 73 | size_t i; 74 | unsigned int dif = 0; 75 | for (i = 0; i < 16; i++) 76 | dif |= (mac1[i] ^ mac2[i]); 77 | dif = (dif - 1) >> ((sizeof(unsigned int) * 8) - 1); 78 | return (dif & 1); 79 | } 80 | 81 | 82 | /* test a few basic operations */ 83 | int 84 | poly1305_power_on_self_test(void) { 85 | /* example from nacl */ 86 | static const unsigned char nacl_key[32] = { 87 | 0xee,0xa6,0xa7,0x25,0x1c,0x1e,0x72,0x91, 88 | 0x6d,0x11,0xc2,0xcb,0x21,0x4d,0x3c,0x25, 89 | 0x25,0x39,0x12,0x1d,0x8e,0x23,0x4e,0x65, 90 | 0x2d,0x65,0x1f,0xa4,0xc8,0xcf,0xf8,0x80, 91 | }; 92 | 93 | static const unsigned char nacl_msg[131] = { 94 | 0x8e,0x99,0x3b,0x9f,0x48,0x68,0x12,0x73, 95 | 0xc2,0x96,0x50,0xba,0x32,0xfc,0x76,0xce, 96 | 0x48,0x33,0x2e,0xa7,0x16,0x4d,0x96,0xa4, 97 | 0x47,0x6f,0xb8,0xc5,0x31,0xa1,0x18,0x6a, 98 | 0xc0,0xdf,0xc1,0x7c,0x98,0xdc,0xe8,0x7b, 99 | 0x4d,0xa7,0xf0,0x11,0xec,0x48,0xc9,0x72, 100 | 0x71,0xd2,0xc2,0x0f,0x9b,0x92,0x8f,0xe2, 101 | 0x27,0x0d,0x6f,0xb8,0x63,0xd5,0x17,0x38, 102 | 0xb4,0x8e,0xee,0xe3,0x14,0xa7,0xcc,0x8a, 103 | 0xb9,0x32,0x16,0x45,0x48,0xe5,0x26,0xae, 104 | 0x90,0x22,0x43,0x68,0x51,0x7a,0xcf,0xea, 105 | 0xbd,0x6b,0xb3,0x73,0x2b,0xc0,0xe9,0xda, 106 | 0x99,0x83,0x2b,0x61,0xca,0x01,0xb6,0xde, 107 | 0x56,0x24,0x4a,0x9e,0x88,0xd5,0xf9,0xb3, 108 | 0x79,0x73,0xf6,0x22,0xa4,0x3d,0x14,0xa6, 109 | 0x59,0x9b,0x1f,0x65,0x4c,0xb4,0x5a,0x74, 110 | 0xe3,0x55,0xa5 111 | }; 112 | 113 | static const unsigned char nacl_mac[16] = { 114 | 0xf3,0xff,0xc7,0x70,0x3f,0x94,0x00,0xe5, 115 | 0x2a,0x7d,0xfb,0x4b,0x3d,0x33,0x05,0xd9 116 | }; 117 | 118 | /* generates a final value of (2^130 - 2) == 3 */ 119 | static const unsigned char wrap_key[32] = { 120 | 0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 121 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 122 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 123 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 124 | }; 125 | 126 | static const unsigned char wrap_msg[16] = { 127 | 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, 128 | 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff 129 | }; 130 | 131 | static const unsigned char wrap_mac[16] = { 132 | 0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 133 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 134 | }; 135 | 136 | /* 137 | mac of the macs of messages of length 0 to 256, where the key and messages 138 | have all their values set to the length 139 | */ 140 | static const unsigned char total_key[32] = { 141 | 0x01,0x02,0x03,0x04,0x05,0x06,0x07, 142 | 0xff,0xfe,0xfd,0xfc,0xfb,0xfa,0xf9, 143 | 0xff,0xff,0xff,0xff,0xff,0xff,0xff, 144 | 0xff,0xff,0xff,0xff,0xff,0xff,0xff 145 | }; 146 | 147 | static const unsigned char total_mac[16] = { 148 | 0x64,0xaf,0xe2,0xe8,0xd6,0xad,0x7b,0xbd, 149 | 0xd2,0x87,0xf9,0x7c,0x44,0x62,0x3d,0x39 150 | }; 151 | 152 | poly1305_context ctx; 153 | poly1305_context total_ctx; 154 | unsigned char all_key[32]; 155 | unsigned char all_msg[256]; 156 | unsigned char mac[16]; 157 | size_t i, j; 158 | int result = 1; 159 | 160 | for (i = 0; i < sizeof(mac); i++) 161 | mac[i] = 0; 162 | poly1305_auth(mac, nacl_msg, sizeof(nacl_msg), nacl_key); 163 | result &= poly1305_verify(nacl_mac, mac); 164 | 165 | for (i = 0; i < sizeof(mac); i++) 166 | mac[i] = 0; 167 | poly1305_init(&ctx, nacl_key); 168 | poly1305_update(&ctx, nacl_msg + 0, 32); 169 | poly1305_update(&ctx, nacl_msg + 32, 64); 170 | poly1305_update(&ctx, nacl_msg + 96, 16); 171 | poly1305_update(&ctx, nacl_msg + 112, 8); 172 | poly1305_update(&ctx, nacl_msg + 120, 4); 173 | poly1305_update(&ctx, nacl_msg + 124, 2); 174 | poly1305_update(&ctx, nacl_msg + 126, 1); 175 | poly1305_update(&ctx, nacl_msg + 127, 1); 176 | poly1305_update(&ctx, nacl_msg + 128, 1); 177 | poly1305_update(&ctx, nacl_msg + 129, 1); 178 | poly1305_update(&ctx, nacl_msg + 130, 1); 179 | poly1305_finish(&ctx, mac); 180 | result &= poly1305_verify(nacl_mac, mac); 181 | 182 | for (i = 0; i < sizeof(mac); i++) 183 | mac[i] = 0; 184 | poly1305_auth(mac, wrap_msg, sizeof(wrap_msg), wrap_key); 185 | result &= poly1305_verify(wrap_mac, mac); 186 | 187 | poly1305_init(&total_ctx, total_key); 188 | for (i = 0; i < 256; i++) { 189 | /* set key and message to 'i,i,i..' */ 190 | for (j = 0; j < sizeof(all_key); j++) 191 | all_key[j] = i; 192 | for (j = 0; j < i; j++) 193 | all_msg[j] = i; 194 | poly1305_auth(mac, all_msg, i, all_key); 195 | poly1305_update(&total_ctx, mac, 16); 196 | } 197 | poly1305_finish(&total_ctx, mac); 198 | result &= poly1305_verify(total_mac, mac); 199 | 200 | return result; 201 | } 202 | -------------------------------------------------------------------------------- /poly1305-donna.h: -------------------------------------------------------------------------------- 1 | #ifndef POLY1305_DONNA_H 2 | #define POLY1305_DONNA_H 3 | 4 | #include 5 | 6 | typedef struct poly1305_context { 7 | size_t aligner; 8 | unsigned char opaque[136]; 9 | } poly1305_context; 10 | 11 | void poly1305_init(poly1305_context *ctx, const unsigned char key[32]); 12 | void poly1305_update(poly1305_context *ctx, const unsigned char *m, size_t bytes); 13 | void poly1305_finish(poly1305_context *ctx, unsigned char mac[16]); 14 | void poly1305_auth(unsigned char mac[16], const unsigned char *m, size_t bytes, const unsigned char key[32]); 15 | 16 | int poly1305_verify(const unsigned char mac1[16], const unsigned char mac2[16]); 17 | int poly1305_power_on_self_test(void); 18 | 19 | #endif /* POLY1305_DONNA_H */ 20 | 21 | -------------------------------------------------------------------------------- /rfc7539.c: -------------------------------------------------------------------------------- 1 | // Implementation of the ChaCha20 + Poly1305 AEAD construction 2 | // as described in RFC 7539. 3 | 4 | #include "rfc7539.h" 5 | 6 | // Initialize the ChaCha20 + Poly1305 context for encryption or decryption 7 | // using a 32 byte key and 12 byte nonce as in the RFC 7539 style. 8 | void rfc7539_init(chacha20poly1305_ctx *ctx, uint8_t key[32], uint8_t nonce[12]) { 9 | unsigned char block0[64] = {0}; 10 | 11 | ECRYPT_keysetup(&ctx->chacha20, key, 256, 16); 12 | ctx->chacha20.input[13] = U8TO32_LITTLE(nonce + 0); 13 | ctx->chacha20.input[14] = U8TO32_LITTLE(nonce + 4); 14 | ctx->chacha20.input[15] = U8TO32_LITTLE(nonce + 8); 15 | 16 | // Encrypt 64 bytes of zeros and use the first 32 bytes 17 | // as the Poly1305 key. 18 | ECRYPT_encrypt_bytes(&ctx->chacha20, block0, block0, 64); 19 | poly1305_init(&ctx->poly1305, block0); 20 | } 21 | 22 | // Include authenticated data in the Poly1305 MAC using the RFC 7539 23 | // style with 16 byte padding. This must only be called once and prior 24 | // to encryption or decryption. 25 | void rfc7539_auth(chacha20poly1305_ctx *ctx, uint8_t *in, size_t n) { 26 | uint8_t padding[16] = {0}; 27 | poly1305_update(&ctx->poly1305, in, n); 28 | poly1305_update(&ctx->poly1305, padding, 16 - n%16); 29 | } 30 | 31 | // Compute RFC 7539-style Poly1305 MAC. 32 | void rfc7539_finish(chacha20poly1305_ctx *ctx, int64_t alen, int64_t plen, uint8_t mac[16]) { 33 | uint8_t padding[16] = {0}; 34 | uint8_t lengths[16] = {0}; 35 | 36 | U64TO8_LITTLE(lengths + 0, alen); 37 | U64TO8_LITTLE(lengths + 8, plen); 38 | 39 | poly1305_update(&ctx->poly1305, padding, 16 - plen%16); 40 | poly1305_update(&ctx->poly1305, lengths, 16); 41 | 42 | poly1305_finish(&ctx->poly1305, mac); 43 | } 44 | -------------------------------------------------------------------------------- /rfc7539.h: -------------------------------------------------------------------------------- 1 | #ifndef RFC7539_H 2 | #define RFC7539_H 3 | 4 | #include "chacha20poly1305.h" 5 | 6 | void rfc7539_init(chacha20poly1305_ctx *ctx, uint8_t key[32], uint8_t nonce[12]); 7 | void rfc7539_auth(chacha20poly1305_ctx *ctx, uint8_t *in, size_t n); 8 | void rfc7539_finish(chacha20poly1305_ctx *ctx, int64_t alen, int64_t plen, uint8_t mac[16]); 9 | 10 | #endif // RFC7539_H 11 | -------------------------------------------------------------------------------- /rfc7539_test.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "rfc7539.h" 6 | 7 | void test_rfc7539() { 8 | uint8_t plaintext[] = { 9 | 0x4c, 0x61, 0x64, 0x69, 0x65, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x47, 0x65, 0x6e, 0x74, 0x6c, 10 | 0x65, 0x6d, 0x65, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x61, 0x73, 11 | 0x73, 0x20, 0x6f, 0x66, 0x20, 0x27, 0x39, 0x39, 0x3a, 0x20, 0x49, 0x66, 0x20, 0x49, 0x20, 0x63, 12 | 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x6f, 0x66, 0x66, 0x65, 0x72, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x6f, 13 | 0x6e, 0x6c, 0x79, 0x20, 0x6f, 0x6e, 0x65, 0x20, 0x74, 0x69, 0x70, 0x20, 0x66, 0x6f, 0x72, 0x20, 14 | 0x74, 0x68, 0x65, 0x20, 0x66, 0x75, 0x74, 0x75, 0x72, 0x65, 0x2c, 0x20, 0x73, 0x75, 0x6e, 0x73, 15 | 0x63, 0x72, 0x65, 0x65, 0x6e, 0x20, 0x77, 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x62, 0x65, 0x20, 0x69, 16 | 0x74, 0x2e, 17 | }; 18 | 19 | uint8_t aad[] = { 20 | 0x50, 0x51, 0x52, 0x53, 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 21 | }; 22 | 23 | uint8_t key[] = { 24 | 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 25 | 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 26 | }; 27 | 28 | uint8_t nonce[] = { 29 | 0x07, 0x00, 0x00, 0x00, 30 | 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 31 | }; 32 | 33 | uint8_t ciphertext[] = { 34 | 0xd3, 0x1a, 0x8d, 0x34, 0x64, 0x8e, 0x60, 0xdb, 0x7b, 0x86, 0xaf, 0xbc, 0x53, 0xef, 0x7e, 0xc2, 35 | 0xa4, 0xad, 0xed, 0x51, 0x29, 0x6e, 0x08, 0xfe, 0xa9, 0xe2, 0xb5, 0xa7, 0x36, 0xee, 0x62, 0xd6, 36 | 0x3d, 0xbe, 0xa4, 0x5e, 0x8c, 0xa9, 0x67, 0x12, 0x82, 0xfa, 0xfb, 0x69, 0xda, 0x92, 0x72, 0x8b, 37 | 0x1a, 0x71, 0xde, 0x0a, 0x9e, 0x06, 0x0b, 0x29, 0x05, 0xd6, 0xa5, 0xb6, 0x7e, 0xcd, 0x3b, 0x36, 38 | 0x92, 0xdd, 0xbd, 0x7f, 0x2d, 0x77, 0x8b, 0x8c, 0x98, 0x03, 0xae, 0xe3, 0x28, 0x09, 0x1b, 0x58, 39 | 0xfa, 0xb3, 0x24, 0xe4, 0xfa, 0xd6, 0x75, 0x94, 0x55, 0x85, 0x80, 0x8b, 0x48, 0x31, 0xd7, 0xbc, 40 | 0x3f, 0xf4, 0xde, 0xf0, 0x8e, 0x4b, 0x7a, 0x9d, 0xe5, 0x76, 0xd2, 0x65, 0x86, 0xce, 0xc6, 0x4b, 41 | 0x61, 0x16, 42 | }; 43 | 44 | uint8_t tag[] = { 45 | 0x1a, 0xe1, 0x0b, 0x59, 0x4f, 0x09, 0xe2, 0x6a, 0x7e, 0x90, 0x2e, 0xcb, 0xd0, 0x60, 0x06, 0x91, 46 | }; 47 | 48 | uint8_t actual_ciphertext[sizeof(ciphertext)]; 49 | uint8_t actual_plaintext[sizeof(plaintext)]; 50 | uint8_t actual_tag[sizeof(tag)]; 51 | 52 | chacha20poly1305_ctx ctx; 53 | rfc7539_init(&ctx, key, nonce); 54 | rfc7539_auth(&ctx, aad, sizeof(aad)); 55 | chacha20poly1305_encrypt(&ctx, plaintext, actual_ciphertext, sizeof(plaintext)); 56 | rfc7539_finish(&ctx, sizeof(aad), sizeof(plaintext), actual_tag); 57 | 58 | assert(memcmp(ciphertext, actual_ciphertext, sizeof(ciphertext)) == 0); 59 | assert(memcmp(tag, actual_tag, sizeof(actual_tag)) == 0); 60 | 61 | memset(&ctx, 0, sizeof(ctx)); 62 | 63 | rfc7539_init(&ctx, key, nonce); 64 | rfc7539_auth(&ctx, aad, sizeof(aad)); 65 | chacha20poly1305_decrypt(&ctx, ciphertext, actual_plaintext, sizeof(ciphertext)); 66 | rfc7539_finish(&ctx, sizeof(aad), sizeof(ciphertext), actual_tag); 67 | 68 | assert(memcmp(plaintext, actual_plaintext, sizeof(plaintext)) == 0); 69 | assert(memcmp(tag, actual_tag, sizeof(actual_tag)) == 0); 70 | 71 | printf("RFC 7539 OK!\n"); 72 | } 73 | 74 | int main(int argc, char **argv) { 75 | (void) argc; 76 | (void) argv; 77 | test_rfc7539(); 78 | } 79 | --------------------------------------------------------------------------------