├── .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 |
--------------------------------------------------------------------------------