Branch data Line data Source code
# 1 : : // Copyright (c) 2017-2019 The Bitcoin Core developers
# 2 : : // Distributed under the MIT software license, see the accompanying
# 3 : : // file COPYING or http://www.opensource.org/licenses/mit-license.php.
# 4 : :
# 5 : : // Based on the public domain implementation 'merged' by D. J. Bernstein
# 6 : : // See https://cr.yp.to/chacha.html.
# 7 : :
# 8 : : #include <crypto/common.h>
# 9 : : #include <crypto/chacha20.h>
# 10 : :
# 11 : : #include <string.h>
# 12 : :
# 13 : 1808975910 : constexpr static inline uint32_t rotl32(uint32_t v, int c) { return (v << c) | (v >> (32 - c)); }
# 14 : :
# 15 : : #define QUARTERROUND(a,b,c,d) \
# 16 : 452244120 : a += b; d = rotl32(d ^ a, 16); \
# 17 : 452244120 : c += d; b = rotl32(b ^ c, 12); \
# 18 : 452244120 : a += b; d = rotl32(d ^ a, 8); \
# 19 : 452244120 : c += d; b = rotl32(b ^ c, 7);
# 20 : :
# 21 : : static const unsigned char sigma[] = "expand 32-byte k";
# 22 : : static const unsigned char tau[] = "expand 16-byte k";
# 23 : :
# 24 : : void ChaCha20::SetKey(const unsigned char* k, size_t keylen)
# 25 : 1460028 : {
# 26 : 1460028 : const unsigned char *constants;
# 27 : :
# 28 : 1460028 : input[4] = ReadLE32(k + 0);
# 29 : 1460028 : input[5] = ReadLE32(k + 4);
# 30 : 1460028 : input[6] = ReadLE32(k + 8);
# 31 : 1460028 : input[7] = ReadLE32(k + 12);
# 32 [ + - ]: 1460028 : if (keylen == 32) { /* recommended */
# 33 : 1460028 : k += 16;
# 34 : 1460028 : constants = sigma;
# 35 : 1460028 : } else { /* keylen == 16 */
# 36 : 0 : constants = tau;
# 37 : 0 : }
# 38 : 1460028 : input[8] = ReadLE32(k + 0);
# 39 : 1460028 : input[9] = ReadLE32(k + 4);
# 40 : 1460028 : input[10] = ReadLE32(k + 8);
# 41 : 1460028 : input[11] = ReadLE32(k + 12);
# 42 : 1460028 : input[0] = ReadLE32(constants + 0);
# 43 : 1460028 : input[1] = ReadLE32(constants + 4);
# 44 : 1460028 : input[2] = ReadLE32(constants + 8);
# 45 : 1460028 : input[3] = ReadLE32(constants + 12);
# 46 : 1460028 : input[12] = 0;
# 47 : 1460028 : input[13] = 0;
# 48 : 1460028 : input[14] = 0;
# 49 : 1460028 : input[15] = 0;
# 50 : 1460028 : }
# 51 : :
# 52 : : ChaCha20::ChaCha20()
# 53 : 1693543 : {
# 54 : 1693543 : memset(input, 0, sizeof(input));
# 55 : 1693543 : }
# 56 : :
# 57 : : ChaCha20::ChaCha20(const unsigned char* k, size_t keylen)
# 58 : 1916 : {
# 59 : 1916 : SetKey(k, keylen);
# 60 : 1916 : }
# 61 : :
# 62 : : void ChaCha20::SetIV(uint64_t iv)
# 63 : 18316 : {
# 64 : 18316 : input[14] = iv;
# 65 : 18316 : input[15] = iv >> 32;
# 66 : 18316 : }
# 67 : :
# 68 : : void ChaCha20::Seek(uint64_t pos)
# 69 : 30322 : {
# 70 : 30322 : input[12] = pos;
# 71 : 30322 : input[13] = pos >> 32;
# 72 : 30322 : }
# 73 : :
# 74 : : void ChaCha20::Keystream(unsigned char* c, size_t bytes)
# 75 : 5605501 : {
# 76 : 5605501 : uint32_t x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15;
# 77 : 5605501 : uint32_t j0, j1, j2, j3, j4, j5, j6, j7, j8, j9, j10, j11, j12, j13, j14, j15;
# 78 : 5605501 : unsigned char *ctarget = nullptr;
# 79 : 5605501 : unsigned char tmp[64];
# 80 : 5605501 : unsigned int i;
# 81 : :
# 82 [ - + ]: 5605501 : if (!bytes) return;
# 83 : :
# 84 : 5605501 : j0 = input[0];
# 85 : 5605501 : j1 = input[1];
# 86 : 5605501 : j2 = input[2];
# 87 : 5605501 : j3 = input[3];
# 88 : 5605501 : j4 = input[4];
# 89 : 5605501 : j5 = input[5];
# 90 : 5605501 : j6 = input[6];
# 91 : 5605501 : j7 = input[7];
# 92 : 5605501 : j8 = input[8];
# 93 : 5605501 : j9 = input[9];
# 94 : 5605501 : j10 = input[10];
# 95 : 5605501 : j11 = input[11];
# 96 : 5605501 : j12 = input[12];
# 97 : 5605501 : j13 = input[13];
# 98 : 5605501 : j14 = input[14];
# 99 : 5605501 : j15 = input[15];
# 100 : :
# 101 : 5617029 : for (;;) {
# 102 [ + + ]: 5617029 : if (bytes < 64) {
# 103 : 3573 : ctarget = c;
# 104 : 3573 : c = tmp;
# 105 : 3573 : }
# 106 : 5617029 : x0 = j0;
# 107 : 5617029 : x1 = j1;
# 108 : 5617029 : x2 = j2;
# 109 : 5617029 : x3 = j3;
# 110 : 5617029 : x4 = j4;
# 111 : 5617029 : x5 = j5;
# 112 : 5617029 : x6 = j6;
# 113 : 5617029 : x7 = j7;
# 114 : 5617029 : x8 = j8;
# 115 : 5617029 : x9 = j9;
# 116 : 5617029 : x10 = j10;
# 117 : 5617029 : x11 = j11;
# 118 : 5617029 : x12 = j12;
# 119 : 5617029 : x13 = j13;
# 120 : 5617029 : x14 = j14;
# 121 : 5617029 : x15 = j15;
# 122 [ + + ]: 61787324 : for (i = 20;i > 0;i -= 2) {
# 123 : 56170295 : QUARTERROUND( x0, x4, x8,x12)
# 124 : 56170295 : QUARTERROUND( x1, x5, x9,x13)
# 125 : 56170295 : QUARTERROUND( x2, x6,x10,x14)
# 126 : 56170295 : QUARTERROUND( x3, x7,x11,x15)
# 127 : 56170295 : QUARTERROUND( x0, x5,x10,x15)
# 128 : 56170295 : QUARTERROUND( x1, x6,x11,x12)
# 129 : 56170295 : QUARTERROUND( x2, x7, x8,x13)
# 130 : 56170295 : QUARTERROUND( x3, x4, x9,x14)
# 131 : 56170295 : }
# 132 : 5617029 : x0 += j0;
# 133 : 5617029 : x1 += j1;
# 134 : 5617029 : x2 += j2;
# 135 : 5617029 : x3 += j3;
# 136 : 5617029 : x4 += j4;
# 137 : 5617029 : x5 += j5;
# 138 : 5617029 : x6 += j6;
# 139 : 5617029 : x7 += j7;
# 140 : 5617029 : x8 += j8;
# 141 : 5617029 : x9 += j9;
# 142 : 5617029 : x10 += j10;
# 143 : 5617029 : x11 += j11;
# 144 : 5617029 : x12 += j12;
# 145 : 5617029 : x13 += j13;
# 146 : 5617029 : x14 += j14;
# 147 : 5617029 : x15 += j15;
# 148 : :
# 149 : 5617029 : ++j12;
# 150 [ - + ]: 5617029 : if (!j12) ++j13;
# 151 : :
# 152 : 5617029 : WriteLE32(c + 0, x0);
# 153 : 5617029 : WriteLE32(c + 4, x1);
# 154 : 5617029 : WriteLE32(c + 8, x2);
# 155 : 5617029 : WriteLE32(c + 12, x3);
# 156 : 5617029 : WriteLE32(c + 16, x4);
# 157 : 5617029 : WriteLE32(c + 20, x5);
# 158 : 5617029 : WriteLE32(c + 24, x6);
# 159 : 5617029 : WriteLE32(c + 28, x7);
# 160 : 5617029 : WriteLE32(c + 32, x8);
# 161 : 5617029 : WriteLE32(c + 36, x9);
# 162 : 5617029 : WriteLE32(c + 40, x10);
# 163 : 5617029 : WriteLE32(c + 44, x11);
# 164 : 5617029 : WriteLE32(c + 48, x12);
# 165 : 5617029 : WriteLE32(c + 52, x13);
# 166 : 5617029 : WriteLE32(c + 56, x14);
# 167 : 5617029 : WriteLE32(c + 60, x15);
# 168 : :
# 169 [ + + ]: 5617029 : if (bytes <= 64) {
# 170 [ + + ]: 5605502 : if (bytes < 64) {
# 171 [ + + ]: 73719 : for (i = 0;i < bytes;++i) ctarget[i] = c[i];
# 172 : 3573 : }
# 173 : 5605502 : input[12] = j12;
# 174 : 5605502 : input[13] = j13;
# 175 : 5605502 : return;
# 176 : 5605502 : }
# 177 : 11527 : bytes -= 64;
# 178 : 11527 : c += 64;
# 179 : 11527 : }
# 180 : 5605501 : }
# 181 : :
# 182 : : void ChaCha20::Crypt(const unsigned char* m, unsigned char* c, size_t bytes)
# 183 : 24014 : {
# 184 : 24014 : uint32_t x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15;
# 185 : 24014 : uint32_t j0, j1, j2, j3, j4, j5, j6, j7, j8, j9, j10, j11, j12, j13, j14, j15;
# 186 : 24014 : unsigned char *ctarget = nullptr;
# 187 : 24014 : unsigned char tmp[64];
# 188 : 24014 : unsigned int i;
# 189 : :
# 190 [ - + ]: 24014 : if (!bytes) return;
# 191 : :
# 192 : 24014 : j0 = input[0];
# 193 : 24014 : j1 = input[1];
# 194 : 24014 : j2 = input[2];
# 195 : 24014 : j3 = input[3];
# 196 : 24014 : j4 = input[4];
# 197 : 24014 : j5 = input[5];
# 198 : 24014 : j6 = input[6];
# 199 : 24014 : j7 = input[7];
# 200 : 24014 : j8 = input[8];
# 201 : 24014 : j9 = input[9];
# 202 : 24014 : j10 = input[10];
# 203 : 24014 : j11 = input[11];
# 204 : 24014 : j12 = input[12];
# 205 : 24014 : j13 = input[13];
# 206 : 24014 : j14 = input[14];
# 207 : 24014 : j15 = input[15];
# 208 : :
# 209 : 36022 : for (;;) {
# 210 [ + + ]: 36022 : if (bytes < 64) {
# 211 : : // if m has fewer than 64 bytes available, copy m to tmp and
# 212 : : // read from tmp instead
# 213 [ + + ]: 880542 : for (i = 0;i < bytes;++i) tmp[i] = m[i];
# 214 : 24014 : m = tmp;
# 215 : 24014 : ctarget = c;
# 216 : 24014 : c = tmp;
# 217 : 24014 : }
# 218 : 36022 : x0 = j0;
# 219 : 36022 : x1 = j1;
# 220 : 36022 : x2 = j2;
# 221 : 36022 : x3 = j3;
# 222 : 36022 : x4 = j4;
# 223 : 36022 : x5 = j5;
# 224 : 36022 : x6 = j6;
# 225 : 36022 : x7 = j7;
# 226 : 36022 : x8 = j8;
# 227 : 36022 : x9 = j9;
# 228 : 36022 : x10 = j10;
# 229 : 36022 : x11 = j11;
# 230 : 36022 : x12 = j12;
# 231 : 36022 : x13 = j13;
# 232 : 36022 : x14 = j14;
# 233 : 36022 : x15 = j15;
# 234 [ + + ]: 396242 : for (i = 20;i > 0;i -= 2) {
# 235 : 360220 : QUARTERROUND( x0, x4, x8,x12)
# 236 : 360220 : QUARTERROUND( x1, x5, x9,x13)
# 237 : 360220 : QUARTERROUND( x2, x6,x10,x14)
# 238 : 360220 : QUARTERROUND( x3, x7,x11,x15)
# 239 : 360220 : QUARTERROUND( x0, x5,x10,x15)
# 240 : 360220 : QUARTERROUND( x1, x6,x11,x12)
# 241 : 360220 : QUARTERROUND( x2, x7, x8,x13)
# 242 : 360220 : QUARTERROUND( x3, x4, x9,x14)
# 243 : 360220 : }
# 244 : 36022 : x0 += j0;
# 245 : 36022 : x1 += j1;
# 246 : 36022 : x2 += j2;
# 247 : 36022 : x3 += j3;
# 248 : 36022 : x4 += j4;
# 249 : 36022 : x5 += j5;
# 250 : 36022 : x6 += j6;
# 251 : 36022 : x7 += j7;
# 252 : 36022 : x8 += j8;
# 253 : 36022 : x9 += j9;
# 254 : 36022 : x10 += j10;
# 255 : 36022 : x11 += j11;
# 256 : 36022 : x12 += j12;
# 257 : 36022 : x13 += j13;
# 258 : 36022 : x14 += j14;
# 259 : 36022 : x15 += j15;
# 260 : :
# 261 : 36022 : x0 ^= ReadLE32(m + 0);
# 262 : 36022 : x1 ^= ReadLE32(m + 4);
# 263 : 36022 : x2 ^= ReadLE32(m + 8);
# 264 : 36022 : x3 ^= ReadLE32(m + 12);
# 265 : 36022 : x4 ^= ReadLE32(m + 16);
# 266 : 36022 : x5 ^= ReadLE32(m + 20);
# 267 : 36022 : x6 ^= ReadLE32(m + 24);
# 268 : 36022 : x7 ^= ReadLE32(m + 28);
# 269 : 36022 : x8 ^= ReadLE32(m + 32);
# 270 : 36022 : x9 ^= ReadLE32(m + 36);
# 271 : 36022 : x10 ^= ReadLE32(m + 40);
# 272 : 36022 : x11 ^= ReadLE32(m + 44);
# 273 : 36022 : x12 ^= ReadLE32(m + 48);
# 274 : 36022 : x13 ^= ReadLE32(m + 52);
# 275 : 36022 : x14 ^= ReadLE32(m + 56);
# 276 : 36022 : x15 ^= ReadLE32(m + 60);
# 277 : :
# 278 : 36022 : ++j12;
# 279 [ - + ]: 36022 : if (!j12) ++j13;
# 280 : :
# 281 : 36022 : WriteLE32(c + 0, x0);
# 282 : 36022 : WriteLE32(c + 4, x1);
# 283 : 36022 : WriteLE32(c + 8, x2);
# 284 : 36022 : WriteLE32(c + 12, x3);
# 285 : 36022 : WriteLE32(c + 16, x4);
# 286 : 36022 : WriteLE32(c + 20, x5);
# 287 : 36022 : WriteLE32(c + 24, x6);
# 288 : 36022 : WriteLE32(c + 28, x7);
# 289 : 36022 : WriteLE32(c + 32, x8);
# 290 : 36022 : WriteLE32(c + 36, x9);
# 291 : 36022 : WriteLE32(c + 40, x10);
# 292 : 36022 : WriteLE32(c + 44, x11);
# 293 : 36022 : WriteLE32(c + 48, x12);
# 294 : 36022 : WriteLE32(c + 52, x13);
# 295 : 36022 : WriteLE32(c + 56, x14);
# 296 : 36022 : WriteLE32(c + 60, x15);
# 297 : :
# 298 [ + + ]: 36022 : if (bytes <= 64) {
# 299 [ + - ]: 24014 : if (bytes < 64) {
# 300 [ + + ]: 880542 : for (i = 0;i < bytes;++i) ctarget[i] = c[i];
# 301 : 24014 : }
# 302 : 24014 : input[12] = j12;
# 303 : 24014 : input[13] = j13;
# 304 : 24014 : return;
# 305 : 24014 : }
# 306 : 12008 : bytes -= 64;
# 307 : 12008 : c += 64;
# 308 : 12008 : m += 64;
# 309 : 12008 : }
# 310 : 24014 : }
|