OLD | NEW |
| (Empty) |
1 /* This Source Code Form is subject to the terms of the Mozilla Public | |
2 * License, v. 2.0. If a copy of the MPL was not distributed with this | |
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ | |
4 | |
5 /* Adopted from the public domain code in NaCl by djb. */ | |
6 | |
7 #include <string.h> | |
8 #include <stdio.h> | |
9 | |
10 #include "prtypes.h" | |
11 #include "secport.h" | |
12 #include "chacha20.h" | |
13 | |
14 #if defined(_MSC_VER) | |
15 #pragma intrinsic(_lrotl) | |
16 #define ROTL32(x, n) _lrotl(x, n) | |
17 #else | |
18 #define ROTL32(x, n) ((x << n) | (x >> ((8 * sizeof x) - n))) | |
19 #endif | |
20 | |
21 #define ROTATE(v, c) ROTL32((v), (c)) | |
22 | |
23 #define U32TO8_LITTLE(p, v) \ | |
24 { (p)[0] = ((v) ) & 0xff; (p)[1] = ((v) >> 8) & 0xff; \ | |
25 (p)[2] = ((v) >> 16) & 0xff; (p)[3] = ((v) >> 24) & 0xff; } | |
26 #define U8TO32_LITTLE(p) \ | |
27 (((PRUint32)((p)[0]) ) | ((PRUint32)((p)[1]) << 8) | \ | |
28 ((PRUint32)((p)[2]) << 16) | ((PRUint32)((p)[3]) << 24)) | |
29 | |
30 #define QUARTERROUND(x, a, b, c, d) \ | |
31 x[a] = x[a] + x[b]; x[d] = ROTATE(x[d] ^ x[a], 16); \ | |
32 x[c] = x[c] + x[d]; x[b] = ROTATE(x[b] ^ x[c], 12); \ | |
33 x[a] = x[a] + x[b]; x[d] = ROTATE(x[d] ^ x[a], 8); \ | |
34 x[c] = x[c] + x[d]; x[b] = ROTATE(x[b] ^ x[c], 7); | |
35 | |
36 static void | |
37 ChaChaCore(unsigned char output[64], const PRUint32 input[16], int num_rounds) | |
38 { | |
39 PRUint32 x[16]; | |
40 int i; | |
41 | |
42 PORT_Memcpy(x, input, sizeof(PRUint32) * 16); | |
43 for (i = num_rounds; i > 0; i -= 2) { | |
44 QUARTERROUND(x, 0, 4, 8, 12) | |
45 QUARTERROUND(x, 1, 5, 9, 13) | |
46 QUARTERROUND(x, 2, 6, 10, 14) | |
47 QUARTERROUND(x, 3, 7, 11, 15) | |
48 QUARTERROUND(x, 0, 5, 10, 15) | |
49 QUARTERROUND(x, 1, 6, 11, 12) | |
50 QUARTERROUND(x, 2, 7, 8, 13) | |
51 QUARTERROUND(x, 3, 4, 9, 14) | |
52 } | |
53 | |
54 for (i = 0; i < 16; ++i) { | |
55 x[i] = x[i] + input[i]; | |
56 } | |
57 for (i = 0; i < 16; ++i) { | |
58 U32TO8_LITTLE(output + 4 * i, x[i]); | |
59 } | |
60 } | |
61 | |
62 static const unsigned char sigma[16] = "expand 32-byte k"; | |
63 | |
64 void | |
65 ChaCha20XOR(unsigned char *out, const unsigned char *in, unsigned int inLen, | |
66 const unsigned char key[32], const unsigned char nonce[12], | |
67 uint32_t counter) | |
68 { | |
69 unsigned char block[64]; | |
70 PRUint32 input[16]; | |
71 unsigned int i; | |
72 | |
73 input[4] = U8TO32_LITTLE(key + 0); | |
74 input[5] = U8TO32_LITTLE(key + 4); | |
75 input[6] = U8TO32_LITTLE(key + 8); | |
76 input[7] = U8TO32_LITTLE(key + 12); | |
77 | |
78 input[8] = U8TO32_LITTLE(key + 16); | |
79 input[9] = U8TO32_LITTLE(key + 20); | |
80 input[10] = U8TO32_LITTLE(key + 24); | |
81 input[11] = U8TO32_LITTLE(key + 28); | |
82 | |
83 input[0] = U8TO32_LITTLE(sigma + 0); | |
84 input[1] = U8TO32_LITTLE(sigma + 4); | |
85 input[2] = U8TO32_LITTLE(sigma + 8); | |
86 input[3] = U8TO32_LITTLE(sigma + 12); | |
87 | |
88 input[12] = counter; | |
89 input[13] = U8TO32_LITTLE(nonce + 0); | |
90 input[14] = U8TO32_LITTLE(nonce + 4); | |
91 input[15] = U8TO32_LITTLE(nonce + 8); | |
92 | |
93 while (inLen >= 64) { | |
94 ChaChaCore(block, input, 20); | |
95 for (i = 0; i < 64; i++) { | |
96 out[i] = in[i] ^ block[i]; | |
97 } | |
98 | |
99 input[12]++; | |
100 inLen -= 64; | |
101 in += 64; | |
102 out += 64; | |
103 } | |
104 | |
105 if (inLen > 0) { | |
106 ChaChaCore(block, input, 20); | |
107 for (i = 0; i < inLen; i++) { | |
108 out[i] = in[i] ^ block[i]; | |
109 } | |
110 } | |
111 } | |
OLD | NEW |