Raven Core  3.0.0
P2P Digital Currency
chacha20.cpp
Go to the documentation of this file.
1 // Copyright (c) 2017 The Bitcoin Core developers
2 // Copyright (c) 2017-2019 The Raven Core developers
3 // Distributed under the MIT software license, see the accompanying
4 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
5 
6 // Based on the public domain implementation 'merged' by D. J. Bernstein
7 // See https://cr.yp.to/chacha.html.
8 
9 #include "crypto/common.h"
10 #include "crypto/chacha20.h"
11 
12 #include <string.h>
13 
14 constexpr static inline uint32_t rotl32(uint32_t v, int c) { return (v << c) | (v >> (32 - c)); }
15 
16 #define QUARTERROUND(a,b,c,d) \
17  a += b; d = rotl32(d ^ a, 16); \
18  c += d; b = rotl32(b ^ c, 12); \
19  a += b; d = rotl32(d ^ a, 8); \
20  c += d; b = rotl32(b ^ c, 7);
21 
22 static const unsigned char sigma[] = "expand 32-byte k";
23 static const unsigned char tau[] = "expand 16-byte k";
24 
25 void ChaCha20::SetKey(const unsigned char* k, size_t keylen)
26 {
27  const unsigned char *constants;
28 
29  input[4] = ReadLE32(k + 0);
30  input[5] = ReadLE32(k + 4);
31  input[6] = ReadLE32(k + 8);
32  input[7] = ReadLE32(k + 12);
33  if (keylen == 32) { /* recommended */
34  k += 16;
35  constants = sigma;
36  } else { /* keylen == 16 */
37  constants = tau;
38  }
39  input[8] = ReadLE32(k + 0);
40  input[9] = ReadLE32(k + 4);
41  input[10] = ReadLE32(k + 8);
42  input[11] = ReadLE32(k + 12);
43  input[0] = ReadLE32(constants + 0);
44  input[1] = ReadLE32(constants + 4);
45  input[2] = ReadLE32(constants + 8);
46  input[3] = ReadLE32(constants + 12);
47  input[12] = 0;
48  input[13] = 0;
49  input[14] = 0;
50  input[15] = 0;
51 }
52 
54 {
55  memset(input, 0, sizeof(input));
56 }
57 
58 ChaCha20::ChaCha20(const unsigned char* k, size_t keylen)
59 {
60  SetKey(k, keylen);
61 }
62 
63 void ChaCha20::SetIV(uint64_t iv)
64 {
65  input[14] = iv;
66  input[15] = iv >> 32;
67 }
68 
69 void ChaCha20::Seek(uint64_t pos)
70 {
71  input[12] = pos;
72  input[13] = pos >> 32;
73 }
74 
75 void ChaCha20::Output(unsigned char* c, size_t bytes)
76 {
77  uint32_t x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15;
78  uint32_t j0, j1, j2, j3, j4, j5, j6, j7, j8, j9, j10, j11, j12, j13, j14, j15;
79  unsigned char *ctarget = nullptr;
80  unsigned char tmp[64];
81  unsigned int i;
82 
83  if (!bytes) return;
84 
85  j0 = input[0];
86  j1 = input[1];
87  j2 = input[2];
88  j3 = input[3];
89  j4 = input[4];
90  j5 = input[5];
91  j6 = input[6];
92  j7 = input[7];
93  j8 = input[8];
94  j9 = input[9];
95  j10 = input[10];
96  j11 = input[11];
97  j12 = input[12];
98  j13 = input[13];
99  j14 = input[14];
100  j15 = input[15];
101 
102  for (;;) {
103  if (bytes < 64) {
104  ctarget = c;
105  c = tmp;
106  }
107  x0 = j0;
108  x1 = j1;
109  x2 = j2;
110  x3 = j3;
111  x4 = j4;
112  x5 = j5;
113  x6 = j6;
114  x7 = j7;
115  x8 = j8;
116  x9 = j9;
117  x10 = j10;
118  x11 = j11;
119  x12 = j12;
120  x13 = j13;
121  x14 = j14;
122  x15 = j15;
123  for (i = 20;i > 0;i -= 2) {
124  QUARTERROUND( x0, x4, x8,x12)
125  QUARTERROUND( x1, x5, x9,x13)
126  QUARTERROUND( x2, x6,x10,x14)
127  QUARTERROUND( x3, x7,x11,x15)
128  QUARTERROUND( x0, x5,x10,x15)
129  QUARTERROUND( x1, x6,x11,x12)
130  QUARTERROUND( x2, x7, x8,x13)
131  QUARTERROUND( x3, x4, x9,x14)
132  }
133  x0 += j0;
134  x1 += j1;
135  x2 += j2;
136  x3 += j3;
137  x4 += j4;
138  x5 += j5;
139  x6 += j6;
140  x7 += j7;
141  x8 += j8;
142  x9 += j9;
143  x10 += j10;
144  x11 += j11;
145  x12 += j12;
146  x13 += j13;
147  x14 += j14;
148  x15 += j15;
149 
150  ++j12;
151  if (!j12) ++j13;
152 
153  WriteLE32(c + 0, x0);
154  WriteLE32(c + 4, x1);
155  WriteLE32(c + 8, x2);
156  WriteLE32(c + 12, x3);
157  WriteLE32(c + 16, x4);
158  WriteLE32(c + 20, x5);
159  WriteLE32(c + 24, x6);
160  WriteLE32(c + 28, x7);
161  WriteLE32(c + 32, x8);
162  WriteLE32(c + 36, x9);
163  WriteLE32(c + 40, x10);
164  WriteLE32(c + 44, x11);
165  WriteLE32(c + 48, x12);
166  WriteLE32(c + 52, x13);
167  WriteLE32(c + 56, x14);
168  WriteLE32(c + 60, x15);
169 
170  if (bytes <= 64) {
171  if (bytes < 64) {
172  for (i = 0;i < bytes;++i) ctarget[i] = c[i];
173  }
174  input[12] = j12;
175  input[13] = j13;
176  return;
177  }
178  bytes -= 64;
179  c += 64;
180  }
181 }
uint32_t input[16]
Definition: chacha20.h:16
void Output(unsigned char *output, size_t bytes)
Definition: chacha20.cpp:75
ChaCha20()
Definition: chacha20.cpp:53
#define QUARTERROUND(a, b, c, d)
Definition: chacha20.cpp:16
void Seek(uint64_t pos)
Definition: chacha20.cpp:69
void SetKey(const unsigned char *key, size_t keylen)
Definition: chacha20.cpp:25
void SetIV(uint64_t iv)
Definition: chacha20.cpp:63