1 /* This file is derived from sober128 implementation in corosync
2    cluster engine. corosync cluster engine borrows the implementation
3    from LibTomCrypt.
4 
5    The latest version of the original code can be found at
6    http://www.libtom.net/LibTomCrypt/ according to which this code is in the
7    Public Domain
8    */
9 
10 /* About LibTomCrypt:
11  * ---------------------------------------------------------------------
12  * LibTomCrypt, modular cryptographic library -- Tom St Denis
13  *
14  * LibTomCrypt is a library that provides various cryptographic
15  * algorithms in a highly modular and flexible manner.
16  *
17  * The library is free for all purposes without any express
18  * guarantee it works.
19  *
20  * Tom St Denis, tomstdenis@iahu.ca, http://www.libtom.net/LibTomCrypt/
21  */
22 
23 #include "sober128.h"
24 
25 typedef unsigned long ulong32;
26 typedef unsigned long long ulong64;
27 
28 /* ---- HELPER MACROS ---- */
29 #define STORE32L(x, y)                                                                     \
30      { (y)[3] = (unsigned char)(((x)>>24)&255); (y)[2] = (unsigned char)(((x)>>16)&255);   \
31        (y)[1] = (unsigned char)(((x)>>8)&255); (y)[0] = (unsigned char)((x)&255); }
32 
33 #define LOAD32L(x, y)                            \
34      { x = ((unsigned long)((y)[3] & 255)<<24) | \
35            ((unsigned long)((y)[2] & 255)<<16) | \
36            ((unsigned long)((y)[1] & 255)<<8)  | \
37            ((unsigned long)((y)[0] & 255)); }
38 
39 /* rotates the hard way */
40 #define ROR(x, y) ( ((((unsigned long)(x)&0xFFFFFFFFUL)>>(unsigned long)((y)&31)) | ((unsigned long)(x)<<(unsigned long)(32-((y)&31)))) & 0xFFFFFFFFUL)
41 
42 
43 /* Id: s128multab.h 213 2003-12-16 04:27:12Z ggr $ */
44 /* @(#)TuringMultab.h   1.3 (QUALCOMM) 02/09/03 */
45 /* Multiplication table for Turing using 0xD02B4367 */
46 
47 static const ulong32 Multab[256] = {
48     0x00000000, 0xD02B4367, 0xED5686CE, 0x3D7DC5A9,
49     0x97AC41D1, 0x478702B6, 0x7AFAC71F, 0xAAD18478,
50     0x631582EF, 0xB33EC188, 0x8E430421, 0x5E684746,
51     0xF4B9C33E, 0x24928059, 0x19EF45F0, 0xC9C40697,
52     0xC62A4993, 0x16010AF4, 0x2B7CCF5D, 0xFB578C3A,
53     0x51860842, 0x81AD4B25, 0xBCD08E8C, 0x6CFBCDEB,
54     0xA53FCB7C, 0x7514881B, 0x48694DB2, 0x98420ED5,
55     0x32938AAD, 0xE2B8C9CA, 0xDFC50C63, 0x0FEE4F04,
56     0xC154926B, 0x117FD10C, 0x2C0214A5, 0xFC2957C2,
57     0x56F8D3BA, 0x86D390DD, 0xBBAE5574, 0x6B851613,
58     0xA2411084, 0x726A53E3, 0x4F17964A, 0x9F3CD52D,
59     0x35ED5155, 0xE5C61232, 0xD8BBD79B, 0x089094FC,
60     0x077EDBF8, 0xD755989F, 0xEA285D36, 0x3A031E51,
61     0x90D29A29, 0x40F9D94E, 0x7D841CE7, 0xADAF5F80,
62     0x646B5917, 0xB4401A70, 0x893DDFD9, 0x59169CBE,
63     0xF3C718C6, 0x23EC5BA1, 0x1E919E08, 0xCEBADD6F,
64     0xCFA869D6, 0x1F832AB1, 0x22FEEF18, 0xF2D5AC7F,
65     0x58042807, 0x882F6B60, 0xB552AEC9, 0x6579EDAE,
66     0xACBDEB39, 0x7C96A85E, 0x41EB6DF7, 0x91C02E90,
67     0x3B11AAE8, 0xEB3AE98F, 0xD6472C26, 0x066C6F41,
68     0x09822045, 0xD9A96322, 0xE4D4A68B, 0x34FFE5EC,
69     0x9E2E6194, 0x4E0522F3, 0x7378E75A, 0xA353A43D,
70     0x6A97A2AA, 0xBABCE1CD, 0x87C12464, 0x57EA6703,
71     0xFD3BE37B, 0x2D10A01C, 0x106D65B5, 0xC04626D2,
72     0x0EFCFBBD, 0xDED7B8DA, 0xE3AA7D73, 0x33813E14,
73     0x9950BA6C, 0x497BF90B, 0x74063CA2, 0xA42D7FC5,
74     0x6DE97952, 0xBDC23A35, 0x80BFFF9C, 0x5094BCFB,
75     0xFA453883, 0x2A6E7BE4, 0x1713BE4D, 0xC738FD2A,
76     0xC8D6B22E, 0x18FDF149, 0x258034E0, 0xF5AB7787,
77     0x5F7AF3FF, 0x8F51B098, 0xB22C7531, 0x62073656,
78     0xABC330C1, 0x7BE873A6, 0x4695B60F, 0x96BEF568,
79     0x3C6F7110, 0xEC443277, 0xD139F7DE, 0x0112B4B9,
80     0xD31DD2E1, 0x03369186, 0x3E4B542F, 0xEE601748,
81     0x44B19330, 0x949AD057, 0xA9E715FE, 0x79CC5699,
82     0xB008500E, 0x60231369, 0x5D5ED6C0, 0x8D7595A7,
83     0x27A411DF, 0xF78F52B8, 0xCAF29711, 0x1AD9D476,
84     0x15379B72, 0xC51CD815, 0xF8611DBC, 0x284A5EDB,
85     0x829BDAA3, 0x52B099C4, 0x6FCD5C6D, 0xBFE61F0A,
86     0x7622199D, 0xA6095AFA, 0x9B749F53, 0x4B5FDC34,
87     0xE18E584C, 0x31A51B2B, 0x0CD8DE82, 0xDCF39DE5,
88     0x1249408A, 0xC26203ED, 0xFF1FC644, 0x2F348523,
89     0x85E5015B, 0x55CE423C, 0x68B38795, 0xB898C4F2,
90     0x715CC265, 0xA1778102, 0x9C0A44AB, 0x4C2107CC,
91     0xE6F083B4, 0x36DBC0D3, 0x0BA6057A, 0xDB8D461D,
92     0xD4630919, 0x04484A7E, 0x39358FD7, 0xE91ECCB0,
93     0x43CF48C8, 0x93E40BAF, 0xAE99CE06, 0x7EB28D61,
94     0xB7768BF6, 0x675DC891, 0x5A200D38, 0x8A0B4E5F,
95     0x20DACA27, 0xF0F18940, 0xCD8C4CE9, 0x1DA70F8E,
96     0x1CB5BB37, 0xCC9EF850, 0xF1E33DF9, 0x21C87E9E,
97     0x8B19FAE6, 0x5B32B981, 0x664F7C28, 0xB6643F4F,
98     0x7FA039D8, 0xAF8B7ABF, 0x92F6BF16, 0x42DDFC71,
99     0xE80C7809, 0x38273B6E, 0x055AFEC7, 0xD571BDA0,
100     0xDA9FF2A4, 0x0AB4B1C3, 0x37C9746A, 0xE7E2370D,
101     0x4D33B375, 0x9D18F012, 0xA06535BB, 0x704E76DC,
102     0xB98A704B, 0x69A1332C, 0x54DCF685, 0x84F7B5E2,
103     0x2E26319A, 0xFE0D72FD, 0xC370B754, 0x135BF433,
104     0xDDE1295C, 0x0DCA6A3B, 0x30B7AF92, 0xE09CECF5,
105     0x4A4D688D, 0x9A662BEA, 0xA71BEE43, 0x7730AD24,
106     0xBEF4ABB3, 0x6EDFE8D4, 0x53A22D7D, 0x83896E1A,
107     0x2958EA62, 0xF973A905, 0xC40E6CAC, 0x14252FCB,
108     0x1BCB60CF, 0xCBE023A8, 0xF69DE601, 0x26B6A566,
109     0x8C67211E, 0x5C4C6279, 0x6131A7D0, 0xB11AE4B7,
110     0x78DEE220, 0xA8F5A147, 0x958864EE, 0x45A32789,
111     0xEF72A3F1, 0x3F59E096, 0x0224253F, 0xD20F6658,
112 };
113 
114 /* Id: s128sbox.h 213 2003-12-16 04:27:12Z ggr $ */
115 /* Sbox for SOBER-128 */
116 /*
117  * This is really the combination of two SBoxes; the least significant
118  * 24 bits comes from:
119  * 8->32 Sbox generated by Millan et. al. at Queensland University of
120  * Technology. See: E. Dawson, W. Millan, L. Burnett, G. Carter,
121  * "On the Design of 8*32 S-boxes". Unpublished report, by the
122  * Information Systems Research Centre,
123  * Queensland University of Technology, 1999.
124  *
125  * The most significant 8 bits are the Skipjack "F table", which can be
126  * found at http://csrc.nist.gov/CryptoToolkit/skipjack/skipjack.pdf .
127  * In this optimised table, though, the intent is to XOR the word from
128  * the table selected by the high byte with the input word. Thus, the
129  * high byte is actually the Skipjack F-table entry XORED with its
130  * table index.
131  */
132 static const ulong32 Sbox[256] = {
133     0xa3aa1887, 0xd65e435c, 0x0b65c042, 0x800e6ef4,
134     0xfc57ee20, 0x4d84fed3, 0xf066c502, 0xf354e8ae,
135     0xbb2ee9d9, 0x281f38d4, 0x1f829b5d, 0x735cdf3c,
136     0x95864249, 0xbc2e3963, 0xa1f4429f, 0xf6432c35,
137     0xf7f40325, 0x3cc0dd70, 0x5f973ded, 0x9902dc5e,
138     0xda175b42, 0x590012bf, 0xdc94d78c, 0x39aab26b,
139     0x4ac11b9a, 0x8c168146, 0xc3ea8ec5, 0x058ac28f,
140     0x52ed5c0f, 0x25b4101c, 0x5a2db082, 0x370929e1,
141     0x2a1843de, 0xfe8299fc, 0x202fbc4b, 0x833915dd,
142     0x33a803fa, 0xd446b2de, 0x46233342, 0x4fcee7c3,
143     0x3ad607ef, 0x9e97ebab, 0x507f859b, 0xe81f2e2f,
144     0xc55b71da, 0xd7e2269a, 0x1339c3d1, 0x7ca56b36,
145     0xa6c9def2, 0xb5c9fc5f, 0x5927b3a3, 0x89a56ddf,
146     0xc625b510, 0x560f85a7, 0xace82e71, 0x2ecb8816,
147     0x44951e2a, 0x97f5f6af, 0xdfcbc2b3, 0xce4ff55d,
148     0xcb6b6214, 0x2b0b83e3, 0x549ea6f5, 0x9de041af,
149     0x792f1f17, 0xf73b99ee, 0x39a65ec0, 0x4c7016c6,
150     0x857709a4, 0xd6326e01, 0xc7b280d9, 0x5cfb1418,
151     0xa6aff227, 0xfd548203, 0x506b9d96, 0xa117a8c0,
152     0x9cd5bf6e, 0xdcee7888, 0x61fcfe64, 0xf7a193cd,
153     0x050d0184, 0xe8ae4930, 0x88014f36, 0xd6a87088,
154     0x6bad6c2a, 0x1422c678, 0xe9204de7, 0xb7c2e759,
155     0x0200248e, 0x013b446b, 0xda0d9fc2, 0x0414a895,
156     0x3a6cc3a1, 0x56fef170, 0x86c19155, 0xcf7b8a66,
157     0x551b5e69, 0xb4a8623e, 0xa2bdfa35, 0xc4f068cc,
158     0x573a6acd, 0x6355e936, 0x03602db9, 0x0edf13c1,
159     0x2d0bb16d, 0x6980b83c, 0xfeb23763, 0x3dd8a911,
160     0x01b6bc13, 0xf55579d7, 0xf55c2fa8, 0x19f4196e,
161     0xe7db5476, 0x8d64a866, 0xc06e16ad, 0xb17fc515,
162     0xc46feb3c, 0x8bc8a306, 0xad6799d9, 0x571a9133,
163     0x992466dd, 0x92eb5dcd, 0xac118f50, 0x9fafb226,
164     0xa1b9cef3, 0x3ab36189, 0x347a19b1, 0x62c73084,
165     0xc27ded5c, 0x6c8bc58f, 0x1cdde421, 0xed1e47fb,
166     0xcdcc715e, 0xb9c0ff99, 0x4b122f0f, 0xc4d25184,
167     0xaf7a5e6c, 0x5bbf18bc, 0x8dd7c6e0, 0x5fb7e420,
168     0x521f523f, 0x4ad9b8a2, 0xe9da1a6b, 0x97888c02,
169     0x19d1e354, 0x5aba7d79, 0xa2cc7753, 0x8c2d9655,
170     0x19829da1, 0x531590a7, 0x19c1c149, 0x3d537f1c,
171     0x50779b69, 0xed71f2b7, 0x463c58fa, 0x52dc4418,
172     0xc18c8c76, 0xc120d9f0, 0xafa80d4d, 0x3b74c473,
173     0xd09410e9, 0x290e4211, 0xc3c8082b, 0x8f6b334a,
174     0x3bf68ed2, 0xa843cc1b, 0x8d3c0ff3, 0x20e564a0,
175     0xf8f55a4f, 0x2b40f8e7, 0xfea7f15f, 0xcf00fe21,
176     0x8a6d37d6, 0xd0d506f1, 0xade00973, 0xefbbde36,
177     0x84670fa8, 0xfa31ab9e, 0xaedab618, 0xc01f52f5,
178     0x6558eb4f, 0x71b9e343, 0x4b8d77dd, 0x8cb93da6,
179     0x740fd52d, 0x425412f8, 0xc5a63360, 0x10e53ad0,
180     0x5a700f1c, 0x8324ed0b, 0xe53dc1ec, 0x1a366795,
181     0x6d549d15, 0xc5ce46d7, 0xe17abe76, 0x5f48e0a0,
182     0xd0f07c02, 0x941249b7, 0xe49ed6ba, 0x37a47f78,
183     0xe1cfffbd, 0xb007ca84, 0xbb65f4da, 0xb59f35da,
184     0x33d2aa44, 0x417452ac, 0xc0d674a7, 0x2d61a46a,
185     0xdc63152a, 0x3e12b7aa, 0x6e615927, 0xa14fb118,
186     0xa151758d, 0xba81687b, 0xe152f0b3, 0x764254ed,
187     0x34c77271, 0x0a31acab, 0x54f94aec, 0xb9e994cd,
188     0x574d9e81, 0x5b623730, 0xce8a21e8, 0x37917f0b,
189     0xe8a9b5d6, 0x9697adf8, 0xf3d30431, 0x5dcac921,
190     0x76b35d46, 0xaa430a36, 0xc2194022, 0x22bca65e,
191     0xdaec70ba, 0xdfaea8cc, 0x777bae8b, 0x242924d5,
192     0x1f098a5a, 0x4b396b81, 0x55de2522, 0x435c1cb8,
193     0xaeb8fe1d, 0x9db3c697, 0x5b164f83, 0xe0c16376,
194     0xa319224c, 0xd0203b35, 0x433ac0fe, 0x1466a19a,
195     0x45f0b24f, 0x51fda998, 0xc0d52d71, 0xfa0896a8,
196     0xf9e6053f, 0xa4b0d300, 0xd499cbcc, 0xb95e3d40,
197 };
198 
199 
200 /* Implementation of SOBER-128 by Tom St Denis.
201  * Based on s128fast.c reference code supplied by Greg Rose of QUALCOMM.
202  */
203 
204 /* don't change these... */
205 #define N                        17
206 #define FOLD                      N /* how many iterations of folding to do */
207 #define INITKONST        0x6996c53a /* value of KONST to use during key loading */
208 #define KEYP                     15 /* where to insert key words */
209 #define FOLDP                     4 /* where to insert non-linear feedback */
210 
BYTE2WORD(const unsigned char * b)211 static ulong32 BYTE2WORD(const unsigned char *b)
212 {
213    ulong32 t;
214    LOAD32L(t, b);
215    return t;
216 }
217 
XORWORD(ulong32 w,unsigned char * b)218 static void XORWORD(ulong32 w, unsigned char *b)
219 {
220    ulong32 t;
221    LOAD32L(t, b);
222    t ^= w;
223    STORE32L(t, b);
224 }
225 
226 /* give correct offset for the current position of the register,
227  * where logically R[0] is at position "zero".
228  */
229 #define OFF(zero, i) (((zero)+(i)) % N)
230 
231 /* step the LFSR */
232 /* After stepping, "zero" moves right one place */
233 #define STEP(R,z) \
234     R[OFF(z,0)] = R[OFF(z,15)] ^ R[OFF(z,4)] ^ (R[OFF(z,0)] << 8) ^ Multab[(R[OFF(z,0)] >> 24) & 0xFF];
235 
cycle(ulong32 * R)236 static void cycle(ulong32 *R)
237 {
238     ulong32 t;
239     int     i;
240 
241     STEP(R,0);
242     t = R[0];
243     for (i = 1; i < N; ++i) {
244         R[i-1] = R[i];
245     }
246     R[N-1] = t;
247 }
248 
249 /* Return a non-linear function of some parts of the register.
250  */
251 #define NLFUNC(c,z) \
252 { \
253     t = c->R[OFF(z,0)] + c->R[OFF(z,16)]; \
254     t ^= Sbox[(t >> 24) & 0xFF]; \
255     t = ROR(t, 8); \
256     t = ((t + c->R[OFF(z,1)]) ^ c->konst) + c->R[OFF(z,6)]; \
257     t ^= Sbox[(t >> 24) & 0xFF]; \
258     t = t + c->R[OFF(z,13)]; \
259 }
260 
nltap(sober128_prng * c)261 static ulong32 nltap(sober128_prng *c)
262 {
263     ulong32 t;
264     NLFUNC(c, 0);
265     return t;
266 }
267 
268 /* initialise to known state
269  */
sober128_start(sober128_prng * c)270 int sober128_start(sober128_prng *c)
271 {
272     int                   i;
273 
274     /* Register initialised to Fibonacci numbers */
275     c->R[0] = 1;
276     c->R[1] = 1;
277     for (i = 2; i < N; ++i) {
278        c->R[i] = c->R[i-1] + c->R[i-2];
279     }
280     c->konst = INITKONST;
281 
282     /* next add_entropy will be the key */
283     c->flag  = 1;
284     c->set   = 0;
285 
286     return 0;
287 }
288 
289 /* Save the current register state
290  */
s128_savestate(sober128_prng * c)291 static void s128_savestate(sober128_prng *c)
292 {
293     int i;
294     for (i = 0; i < N; ++i) {
295         c->initR[i] = c->R[i];
296     }
297 }
298 
299 /* initialise to previously saved register state
300  */
s128_reloadstate(sober128_prng * c)301 static void s128_reloadstate(sober128_prng *c)
302 {
303     int i;
304 
305     for (i = 0; i < N; ++i) {
306         c->R[i] = c->initR[i];
307     }
308 }
309 
310 /* Initialise "konst"
311  */
s128_genkonst(sober128_prng * c)312 static void s128_genkonst(sober128_prng *c)
313 {
314     ulong32 newkonst;
315 
316     do {
317        cycle(c->R);
318        newkonst = nltap(c);
319     } while ((newkonst & 0xFF000000) == 0);
320     c->konst = newkonst;
321 }
322 
323 /* Load key material into the register
324  */
325 #define ADDKEY(k) \
326    c->R[KEYP] += (k);
327 
328 #define XORNL(nl) \
329    c->R[FOLDP] ^= (nl);
330 
331 /* nonlinear diffusion of register for key */
332 #define DROUND(z) STEP(c->R,z); NLFUNC(c,(z+1)); c->R[OFF((z+1),FOLDP)] ^= t;
s128_diffuse(sober128_prng * c)333 static void s128_diffuse(sober128_prng *c)
334 {
335     ulong32 t;
336     /* relies on FOLD == N == 17! */
337     DROUND(0);
338     DROUND(1);
339     DROUND(2);
340     DROUND(3);
341     DROUND(4);
342     DROUND(5);
343     DROUND(6);
344     DROUND(7);
345     DROUND(8);
346     DROUND(9);
347     DROUND(10);
348     DROUND(11);
349     DROUND(12);
350     DROUND(13);
351     DROUND(14);
352     DROUND(15);
353     DROUND(16);
354 }
355 
sober128_add_entropy(const unsigned char * buf,unsigned long len,sober128_prng * c)356 int sober128_add_entropy(const unsigned char *buf, unsigned long len, sober128_prng *c)
357 {
358     ulong32               i, k;
359 
360 
361     if (c->flag == 1) {
362        /* this is the first call to the add_entropy so this input is the key */
363        /* len must be multiple of 4 bytes */
364        /* assert ((len & 3) == 0); */
365 
366        for (i = 0; i < len/4; i++) {
367            k = BYTE2WORD(&buf[i*4]);
368           ADDKEY(k);
369           cycle(c->R);
370           XORNL(nltap(c));
371        }
372 
373        /* also fold in the length of the key */
374        ADDKEY(len);
375 
376        /* now diffuse */
377        s128_diffuse(c);
378 
379        s128_genkonst(c);
380        s128_savestate(c);
381        c->nbuf = 0;
382        c->flag = 0;
383        c->set  = 1;
384     } else {
385        /* ok we are adding an IV then... */
386        s128_reloadstate(c);
387 
388        /* len must be multiple of 4 bytes */
389        /* assert ((len & 3) == 0); */
390 
391        for (i = 0; i < len/4; i++) {
392            k = BYTE2WORD(&buf[i*4]);
393           ADDKEY(k);
394           cycle(c->R);
395           XORNL(nltap(c));
396        }
397 
398        /* also fold in the length of the key */
399        ADDKEY(len);
400 
401        /* now diffuse */
402        s128_diffuse(c);
403        c->nbuf = 0;
404     }
405 
406     return 0;
407 }
408 
409 /* XOR pseudo-random bytes into buffer
410  */
411 #define SROUND(z) STEP(c->R,z); NLFUNC(c,(z+1)); XORWORD(t, buf+(z*4));
412 
sober128_read(unsigned char * buf,unsigned long nbytes,sober128_prng * c)413 unsigned long sober128_read(unsigned char *buf, unsigned long nbytes, sober128_prng *c)
414 {
415    ulong32               t, tlen;
416 
417    tlen = nbytes;
418 
419    /* handle any previously buffered bytes */
420    while (c->nbuf != 0 && nbytes != 0) {
421       *buf++ ^= c->sbuf & 0xFF;
422        c->sbuf >>= 8;
423        c->nbuf -= 8;
424        --nbytes;
425    }
426 
427 #ifndef SMALL_CODE
428     /* do lots at a time, if there's enough to do */
429     while (nbytes >= N*4) {
430       SROUND(0);
431       SROUND(1);
432       SROUND(2);
433       SROUND(3);
434       SROUND(4);
435       SROUND(5);
436       SROUND(6);
437       SROUND(7);
438       SROUND(8);
439       SROUND(9);
440       SROUND(10);
441       SROUND(11);
442       SROUND(12);
443       SROUND(13);
444       SROUND(14);
445       SROUND(15);
446       SROUND(16);
447       buf    += 4*N;
448       nbytes -= 4*N;
449     }
450 #endif
451 
452     /* do small or odd size buffers the slow way */
453     while (4 <= nbytes) {
454       cycle(c->R);
455       t = nltap(c);
456       XORWORD(t, buf);
457       buf    += 4;
458       nbytes -= 4;
459     }
460 
461     /* handle any trailing bytes */
462     if (nbytes != 0) {
463       cycle(c->R);
464       c->sbuf = nltap(c);
465       c->nbuf = 32;
466       while (c->nbuf != 0 && nbytes != 0) {
467         *buf++ ^= c->sbuf & 0xFF;
468         c->sbuf >>= 8;
469         c->nbuf -= 8;
470         --nbytes;
471       }
472     }
473 
474     return tlen;
475 }
476 
477 /*
478  * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
479  *
480  * Local variables:
481  * c-basic-offset: 4
482  * tab-width: 8
483  * indent-tabs-mode: nil
484  * End:
485  *
486  * vi: set shiftwidth=4 tabstop=8 expandtab:
487  * :indentSize=4:tabSize=8:noTabs=true:
488  */
489