File Coverage

ulib/chacha.c
Criterion Covered Total %
statement 93 105 88.5
branch 20 26 76.9
condition n/a
subroutine n/a
pod n/a
total 113 131 86.2


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 215           static void cc_init(pUCXT, const UCHAR *seed, IV init_buffer) {
57 215           cc_st *cc = &SMEM->cc;
58 215           U32 *x = (U32*)&cc->state;
59              
60 215           x[ 0] = 0x61707865;
61 215           x[ 1] = 0x3320646e;
62 215           x[ 2] = 0x79622d32;
63 215           x[ 3] = 0x6b206574;
64 215           x[ 4] = U8TO32_LE(seed + 0);
65 215           x[ 5] = U8TO32_LE(seed + 4);
66 215           x[ 6] = U8TO32_LE(seed + 8);
67 215           x[ 7] = U8TO32_LE(seed + 12);
68 215           x[ 8] = U8TO32_LE(seed + 16);
69 215           x[ 9] = U8TO32_LE(seed + 20);
70 215           x[10] = U8TO32_LE(seed + 24);
71 215           x[11] = U8TO32_LE(seed + 28);
72 215           x[12] = 0;
73 215           x[13] = 0;
74 215           x[14] = U8TO32_LE(seed + 32);
75 215           x[15] = U8TO32_LE(seed + 36);
76              
77 215 50         if (init_buffer) {
78 215           memset(cc->buf, 0, CC_BUFSZ);
79 215           cc->have = 0;
80             }
81 215           }
82              
83 12576           static void cc_core(pUCXT, UCHAR* buf) {
84 12576           cc_st *cc = &SMEM->cc;
85 12576           U32 *s = cc->state;
86             U32 i, x[16];
87              
88 12576           memcpy(x, s, 16*sizeof(U32));
89              
90 138336 100         for (i = 0; i
91 125760           QROUND( x[ 0], x[ 4], x[ 8], x[12] );
92 125760           QROUND( x[ 1], x[ 5], x[ 9], x[13] );
93 125760           QROUND( x[ 2], x[ 6], x[10], x[14] );
94 125760           QROUND( x[ 3], x[ 7], x[11], x[15] );
95 125760           QROUND( x[ 0], x[ 5], x[10], x[15] );
96 125760           QROUND( x[ 1], x[ 6], x[11], x[12] );
97 125760           QROUND( x[ 2], x[ 7], x[ 8], x[13] );
98 125760           QROUND( x[ 3], x[ 4], x[ 9], x[14] );
99             }
100              
101 213792 100         for (i = 0; i < 16; i++)
102 201216           x[i] += s[i];
103              
104 213792 100         for (i = 0; i < 16; i++)
105 201216           U32TO8_LE( buf+4*i, x[i] );
106              
107             /* inc counter */
108 12576 50         if (++s[12] == 0) s[13]++;
109 12576           }
110              
111 786           static U16 cc_stream(pUCXT, UCHAR* buf, U16 n) {
112 786           U16 r = n;
113             UCHAR sbuf[CC_CORESZ];
114              
115 13362 100         while (r >= CC_CORESZ) {
116 12576           cc_core(aUCXT, buf);
117 12576           buf += CC_CORESZ;
118 12576           r -= CC_CORESZ;
119             }
120 786 50         if (r > 0) {
121 0           cc_core(aUCXT, sbuf);
122 0           memcpy(buf, sbuf, r);
123             }
124 786           return n;
125             }
126              
127 786           static U32 cc_refill(pUCXT) {
128 786           cc_st *cc = &SMEM->cc;
129             U64 *cp;
130              
131             /* refill buffer */
132 786           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 786           cp = (U64*)&cc->buf;
165 101394 100         while (cp < (U64*)&cc->have)
166 100608           *cp++ ^= xo_rand(aUCXT);
167 786           return cc->have;
168             }
169              
170 215           void cc_srand(pUCXT) {
171             U64 d, n, *cp;
172             UCHAR data[40];
173              
174 215           sm_srand(aUCXT);
175 215           xo_srand(aUCXT);
176              
177 215           cp = (U64*)&data;
178              
179 215           *cp++ = xo_rand(aUCXT);
180 215           *cp++ = xo_rand(aUCXT);
181 215           *cp++ = xo_rand(aUCXT);
182 215           *cp++ = xo_rand(aUCXT);
183 215           *cp++ = xo_rand(aUCXT);
184              
185 215           cc_init(aUCXT, data, 1);
186              
187             /* stir 8 - 39 times */
188 215           cc_rand64(aUCXT, &d);
189 215           n = 8 + (d >> 59);
190              
191 5773 100         while (n-- > 0)
192 5558           cc_rand64(aUCXT, &d);
193 215           }
194              
195             /* API */
196              
197 14593           void cc_rand16(pUCXT, U16 *out) {
198 14593           cc_st *cc = &SMEM->cc;
199             UCHAR *ptr;
200              
201 14593 100         if (cc->have < 2) cc_refill(aUCXT);
202 14593           ptr = cc->buf + CC_BUFSZ - cc->have;
203 14593           cc->have -= 2;
204              
205 14593           *out = U8TO16_LE(ptr);
206 14593           }
207              
208 28           void cc_rand32(pUCXT, U32 *out) {
209 28           cc_st *cc = &SMEM->cc;
210             UCHAR *ptr;
211              
212 28 50         if (cc->have < 4) cc_refill(aUCXT);
213 28           ptr = cc->buf + CC_BUFSZ - cc->have;
214 28           cc->have -= 4;
215              
216 28           *out = U8TO32_LE(ptr);
217 28           }
218              
219 48220           void cc_rand64(pUCXT, U64 *out) {
220 48220           cc_st *cc = &SMEM->cc;
221             UCHAR *ptr;
222              
223 48220 100         if (cc->have < 8) cc_refill(aUCXT);
224 48220           ptr = cc->buf + CC_BUFSZ - cc->have;
225 48220           cc->have -= 8;
226              
227 48220           *out = U8TO64_LE(ptr);
228 48220           }
229              
230 0           void cc_rand128(pUCXT, void *out) {
231 0           cc_st *cc = &SMEM->cc;
232             U64 a, b;
233             UCHAR *ptr;
234              
235 0 0         if (cc->have < 16) cc_refill(aUCXT);
236 0           ptr = cc->buf + CC_BUFSZ - cc->have;
237 0           cc->have -= 16;
238              
239 0           a = U8TO64_LE(ptr);
240 0           b = U8TO64_LE(ptr);
241 0           *((U64*)out) = a;
242 0           *(((U64*)out)+8) = b;
243 0           }
244              
245             /* ex:set ts=2 sw=2 itab=spaces: */