File Coverage

ulib/chacha.c
Criterion Covered Total %
statement 100 114 87.7
branch 25 34 73.5
condition n/a
subroutine n/a
pod n/a
total 125 148 84.4


line stmt bran cond sub pod time code
1             #ifdef __cplusplus
2             extern "C" {
3             #endif
4              
5             #include "ulib/chacha.h"
6             #include "ulib/splitmix.h"
7             #include "ulib/xoshiro.h"
8              
9             #ifdef __cplusplus
10             }
11             #endif
12              
13             /* perl versions broken on some platforms */
14             #undef U8TO16_LE
15             #define U8TO16_LE(p) ( \
16             ((U16)((p)[0]) ) | \
17             ((U16)((p)[1]) << 8) \
18             )
19             #undef U8TO32_LE
20             #define U8TO32_LE(p) ( \
21             ((U32)((p)[0]) ) | \
22             ((U32)((p)[1]) << 8) | \
23             ((U32)((p)[2]) << 16) | \
24             ((U32)((p)[3]) << 24) \
25             )
26             #undef U8TO64_LE
27             #define U8TO64_LE(p) ( \
28             ((U64)((p)[0]) ) | \
29             ((U64)((p)[1]) << 8) | \
30             ((U64)((p)[2]) << 16) | \
31             ((U64)((p)[3]) << 24) | \
32             ((U64)((p)[4]) << 32) | \
33             ((U64)((p)[5]) << 40) | \
34             ((U64)((p)[6]) << 48) | \
35             ((U64)((p)[7]) << 56) \
36             )
37             #undef U32TO8_LE
38             #define U32TO8_LE(p, v) do { \
39             U32 _v = v; \
40             (p)[0] = (((_v) ) & 0xFFU); \
41             (p)[1] = (((_v) >> 8) & 0xFFU); \
42             (p)[2] = (((_v) >> 16) & 0xFFU); \
43             (p)[3] = (((_v) >> 24) & 0xFFU); \
44             } while (0)
45              
46             /* perls ROTL32 broken too */
47             #define rotl32(x,r) ((((U32)(x)) << (r)) | (((U32)(x)) >> (32 - (r))))
48              
49             #define QROUND(a,b,c,d) \
50             a += b; d = rotl32(d ^ a, 16); \
51             c += d; b = rotl32(b ^ c, 12); \
52             a += b; d = rotl32(d ^ a, 8); \
53             c += d; b = rotl32(b ^ c, 7);
54              
55              
56 104           static void cc_init(pUCXT, const UCHAR *seed, IV init_buffer) {
57 104           cc_st *cc = &UCXT.cc;
58 104           U32 *x = (U32*)&cc->state;
59              
60 104           x[ 0] = 0x61707865;
61 104           x[ 1] = 0x3320646e;
62 104           x[ 2] = 0x79622d32;
63 104           x[ 3] = 0x6b206574;
64 104           x[ 4] = U8TO32_LE(seed + 0);
65 104           x[ 5] = U8TO32_LE(seed + 4);
66 104           x[ 6] = U8TO32_LE(seed + 8);
67 104           x[ 7] = U8TO32_LE(seed + 12);
68 104           x[ 8] = U8TO32_LE(seed + 16);
69 104           x[ 9] = U8TO32_LE(seed + 20);
70 104           x[10] = U8TO32_LE(seed + 24);
71 104           x[11] = U8TO32_LE(seed + 28);
72 104           x[12] = 0;
73 104           x[13] = 0;
74 104           x[14] = U8TO32_LE(seed + 32);
75 104           x[15] = U8TO32_LE(seed + 36);
76              
77 104 50         if (init_buffer) {
78 104           memset(cc->buf, 0, CC_BUFSZ);
79 104           cc->have = 0;
80             }
81 104           }
82              
83 1904           static void cc_core(pUCXT, UCHAR* buf) {
84 1904           cc_st *cc = &UCXT.cc;
85 1904           U32 *s = cc->state;
86             U32 i, x[16];
87              
88 1904           memcpy(x, s, 16*sizeof(U32));
89              
90 20944 100         for (i = 0; i<CC_ROUNDS; i+=2) {
91 19040           QROUND( x[ 0], x[ 4], x[ 8], x[12] );
92 19040           QROUND( x[ 1], x[ 5], x[ 9], x[13] );
93 19040           QROUND( x[ 2], x[ 6], x[10], x[14] );
94 19040           QROUND( x[ 3], x[ 7], x[11], x[15] );
95 19040           QROUND( x[ 0], x[ 5], x[10], x[15] );
96 19040           QROUND( x[ 1], x[ 6], x[11], x[12] );
97 19040           QROUND( x[ 2], x[ 7], x[ 8], x[13] );
98 19040           QROUND( x[ 3], x[ 4], x[ 9], x[14] );
99             }
100              
101 32368 100         for (i = 0; i < 16; i++)
102 30464           x[i] += s[i];
103              
104 32368 100         for (i = 0; i < 16; i++)
105 30464           U32TO8_LE( buf+4*i, x[i] );
106              
107             /* inc counter */
108 1904 50         if (++s[12] == 0) s[13]++;
109 1904           }
110              
111 119           static U16 cc_stream(pUCXT, UCHAR* buf, U16 n) {
112 119           U16 r = n;
113             UCHAR sbuf[CC_CORESZ];
114              
115 2023 100         while (r >= CC_CORESZ) {
116 1904           cc_core(aUCXT, buf);
117 1904           buf += CC_CORESZ;
118 1904           r -= CC_CORESZ;
119             }
120 119 50         if (r > 0) {
121 0           cc_core(aUCXT, sbuf);
122 0           memcpy(buf, sbuf, r);
123             }
124 119           return n;
125             }
126              
127 119           static U32 cc_refill(pUCXT) {
128 119           cc_st *cc = &UCXT.cc;
129             U64 *cp;
130              
131             /* refill buffer */
132 119           cc->have = cc_stream(aUCXT, (UCHAR*)&cc->buf, CC_BUFSZ);
133              
134             /* reseed with KEYSZ bytes from buffer, then zero */
135             /*
136             cc_init(cc.buf, 0);
137             memset(cc.buf, 0, KEYSZ);
138             cc.have = BUFSZ - KEYSZ;
139             return cc.have;
140             */
141              
142             /* create new key */
143             /*
144             UCHAR seed[40];
145             cp = (U64*)&seed;
146             *cp++ = xo_rand();
147             *cp++ = xo_rand();
148             *cp++ = xo_rand();
149             *cp++ = xo_rand();
150             *cp++ = xo_rand();
151             cc_init((UCHAR*)&seed, 0);
152             return cc.have;
153             */
154              
155             /* salt the state */
156             /*
157             cp = (U64*)&cc.state;
158             while (cp < (U64*)&cc.buf)
159             *cp++ ^= (U32)xo_rand();
160             return cc.have;
161             */
162              
163             /* salt the buffer */
164 119           cp = (U64*)&cc->buf;
165 15351 100         while (cp < (U64*)&cc->have)
166 15232           *cp++ ^= xo_rand(aUCXT);
167 119           return cc->have;
168             }
169              
170 104           void cc_srand(pUCXT, Pid_t pid) {
171             U64 d, n, *cp;
172             UCHAR data[40];
173              
174 104           UCXT.cc.pid = pid;
175 104           sm_srand(aUCXT, pid);
176 104           xo_srand(aUCXT, pid);
177              
178 104           cp = (U64*)&data;
179              
180 104           *cp++ = xo_rand(aUCXT);
181 104           *cp++ = xo_rand(aUCXT);
182 104           *cp++ = xo_rand(aUCXT);
183 104           *cp++ = xo_rand(aUCXT);
184 104           *cp++ = xo_rand(aUCXT);
185              
186 104           cc_init(aUCXT, data, 1);
187              
188             /* stir 8 - 39 times */
189 104           cc_rand64(aUCXT, &d);
190 104           n = 8 + (d >> 59);
191              
192 2350 100         while (n-- > 0)
193 2246           cc_rand64(aUCXT, &d);
194 104           }
195              
196             /* API */
197              
198 236           void cc_rand16(pUCXT, U16 *out) {
199 236           cc_st *cc = &UCXT.cc;
200             UCHAR *ptr;
201             Pid_t pid;
202              
203 236 100         if (cc->pid != (pid = getpid()))
204 63           cc_srand(aUCXT, pid);
205              
206 236 50         if (cc->have < 2) cc_refill(aUCXT);
207 236           ptr = cc->buf + CC_BUFSZ - cc->have;
208 236           cc->have -= 2;
209              
210 236           *out = U8TO16_LE(ptr);
211 236           }
212              
213 28           void cc_rand32(pUCXT, U32 *out) {
214 28           cc_st *cc = &UCXT.cc;
215             UCHAR *ptr;
216             Pid_t pid;
217              
218 28 100         if (cc->pid != (pid = getpid()))
219 8           cc_srand(aUCXT, pid);
220              
221 28 50         if (cc->have < 4) cc_refill(aUCXT);
222 28           ptr = cc->buf + CC_BUFSZ - cc->have;
223 28           cc->have -= 4;
224              
225 28           *out = U8TO32_LE(ptr);
226 28           }
227              
228 5397           void cc_rand64(pUCXT, U64 *out) {
229 5397           cc_st *cc = &UCXT.cc;
230             UCHAR *ptr;
231             Pid_t pid;
232              
233 5397 100         if (cc->pid != (pid = getpid()))
234 33           cc_srand(aUCXT, pid);
235              
236 5397 100         if (cc->have < 8) cc_refill(aUCXT);
237 5397           ptr = cc->buf + CC_BUFSZ - cc->have;
238 5397           cc->have -= 8;
239              
240 5397           *out = U8TO64_LE(ptr);
241 5397           }
242              
243 0           void cc_rand128(pUCXT, void *out) {
244 0           cc_st *cc = &UCXT.cc;
245             U64 a, b;
246             UCHAR *ptr;
247             Pid_t pid;
248              
249 0 0         if (cc->pid != (pid = getpid()))
250 0           cc_srand(aUCXT, pid);
251              
252 0 0         if (cc->have < 16) cc_refill(aUCXT);
253 0           ptr = cc->buf + CC_BUFSZ - cc->have;
254 0           cc->have -= 16;
255              
256 0           a = U8TO64_LE(ptr);
257 0           b = U8TO64_LE(ptr);
258 0           *((U64*)out) = a;
259 0           *(((U64*)out)+8) = b;
260 0           }
261              
262             /* ex:set ts=2 sw=2 itab=spaces: */