Mercurial > dropbear
comparison libtomcrypt/src/stream/sober128/sober128_stream.c @ 1471:6dba84798cd5
Update to libtomcrypt 1.18.1, merged with Dropbear changes
author | Matt Johnston <matt@ucc.asn.au> |
---|---|
date | Fri, 09 Feb 2018 21:44:05 +0800 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
1470:8bba51a55704 | 1471:6dba84798cd5 |
---|---|
1 /* LibTomCrypt, modular cryptographic library -- Tom St Denis | |
2 * | |
3 * LibTomCrypt is a library that provides various cryptographic | |
4 * algorithms in a highly modular and flexible manner. | |
5 * | |
6 * The library is free for all purposes without any express | |
7 * guarantee it works. | |
8 */ | |
9 #include "tomcrypt.h" | |
10 | |
11 /** | |
12 @file sober128_stream.c | |
13 Implementation of SOBER-128 by Tom St Denis. | |
14 Based on s128fast.c reference code supplied by Greg Rose of QUALCOMM. | |
15 */ | |
16 | |
17 #ifdef LTC_SOBER128 | |
18 | |
19 #define __LTC_SOBER128TAB_C__ | |
20 #include "sober128tab.c" | |
21 | |
22 /* don't change these... */ | |
23 #define N 17 | |
24 #define FOLD N /* how many iterations of folding to do */ | |
25 #define INITKONST 0x6996c53a /* value of KONST to use during key loading */ | |
26 #define KEYP 15 /* where to insert key words */ | |
27 #define FOLDP 4 /* where to insert non-linear feedback */ | |
28 | |
29 #define B(x,i) ((unsigned char)(((x) >> (8*i)) & 0xFF)) | |
30 | |
31 static ulong32 BYTE2WORD(unsigned char *b) | |
32 { | |
33 ulong32 t; | |
34 LOAD32L(t, b); | |
35 return t; | |
36 } | |
37 | |
38 static void XORWORD(ulong32 w, const unsigned char *in, unsigned char *out) | |
39 { | |
40 ulong32 t; | |
41 LOAD32L(t, in); | |
42 t ^= w; | |
43 STORE32L(t, out); | |
44 } | |
45 | |
46 /* give correct offset for the current position of the register, | |
47 * where logically R[0] is at position "zero". | |
48 */ | |
49 #define OFF(zero, i) (((zero)+(i)) % N) | |
50 | |
51 /* step the LFSR */ | |
52 /* After stepping, "zero" moves right one place */ | |
53 #define STEP(R,z) \ | |
54 R[OFF(z,0)] = R[OFF(z,15)] ^ R[OFF(z,4)] ^ (R[OFF(z,0)] << 8) ^ Multab[(R[OFF(z,0)] >> 24) & 0xFF]; | |
55 | |
56 static void cycle(ulong32 *R) | |
57 { | |
58 ulong32 t; | |
59 int i; | |
60 | |
61 STEP(R,0); | |
62 t = R[0]; | |
63 for (i = 1; i < N; ++i) { | |
64 R[i-1] = R[i]; | |
65 } | |
66 R[N-1] = t; | |
67 } | |
68 | |
69 /* Return a non-linear function of some parts of the register. | |
70 */ | |
71 #define NLFUNC(c,z) \ | |
72 { \ | |
73 t = c->R[OFF(z,0)] + c->R[OFF(z,16)]; \ | |
74 t ^= Sbox[(t >> 24) & 0xFF]; \ | |
75 t = RORc(t, 8); \ | |
76 t = ((t + c->R[OFF(z,1)]) ^ c->konst) + c->R[OFF(z,6)]; \ | |
77 t ^= Sbox[(t >> 24) & 0xFF]; \ | |
78 t = t + c->R[OFF(z,13)]; \ | |
79 } | |
80 | |
81 static ulong32 nltap(sober128_state *c) | |
82 { | |
83 ulong32 t; | |
84 NLFUNC(c, 0); | |
85 return t; | |
86 } | |
87 | |
88 /* Save the current register state | |
89 */ | |
90 static void s128_savestate(sober128_state *c) | |
91 { | |
92 int i; | |
93 for (i = 0; i < N; ++i) { | |
94 c->initR[i] = c->R[i]; | |
95 } | |
96 } | |
97 | |
98 /* initialise to previously saved register state | |
99 */ | |
100 static void s128_reloadstate(sober128_state *c) | |
101 { | |
102 int i; | |
103 | |
104 for (i = 0; i < N; ++i) { | |
105 c->R[i] = c->initR[i]; | |
106 } | |
107 } | |
108 | |
109 /* Initialise "konst" | |
110 */ | |
111 static void s128_genkonst(sober128_state *c) | |
112 { | |
113 ulong32 newkonst; | |
114 | |
115 do { | |
116 cycle(c->R); | |
117 newkonst = nltap(c); | |
118 } while ((newkonst & 0xFF000000) == 0); | |
119 c->konst = newkonst; | |
120 } | |
121 | |
122 /* Load key material into the register | |
123 */ | |
124 #define ADDKEY(k) \ | |
125 c->R[KEYP] += (k); | |
126 | |
127 #define XORNL(nl) \ | |
128 c->R[FOLDP] ^= (nl); | |
129 | |
130 /* nonlinear diffusion of register for key */ | |
131 #define DROUND(z) STEP(c->R,z); NLFUNC(c,(z+1)); c->R[OFF((z+1),FOLDP)] ^= t; | |
132 static void s128_diffuse(sober128_state *c) | |
133 { | |
134 ulong32 t; | |
135 /* relies on FOLD == N == 17! */ | |
136 DROUND(0); | |
137 DROUND(1); | |
138 DROUND(2); | |
139 DROUND(3); | |
140 DROUND(4); | |
141 DROUND(5); | |
142 DROUND(6); | |
143 DROUND(7); | |
144 DROUND(8); | |
145 DROUND(9); | |
146 DROUND(10); | |
147 DROUND(11); | |
148 DROUND(12); | |
149 DROUND(13); | |
150 DROUND(14); | |
151 DROUND(15); | |
152 DROUND(16); | |
153 } | |
154 | |
155 /** | |
156 Initialize an Sober128 context (only the key) | |
157 @param c [out] The destination of the Sober128 state | |
158 @param key The secret key | |
159 @param keylen The length of the secret key (octets) | |
160 @return CRYPT_OK if successful | |
161 */ | |
162 int sober128_stream_setup(sober128_state *c, const unsigned char *key, unsigned long keylen) | |
163 { | |
164 ulong32 i, k; | |
165 | |
166 LTC_ARGCHK(c != NULL); | |
167 LTC_ARGCHK(key != NULL); | |
168 LTC_ARGCHK(keylen > 0); | |
169 | |
170 /* keylen must be multiple of 4 bytes */ | |
171 if ((keylen & 3) != 0) { | |
172 return CRYPT_INVALID_KEYSIZE; | |
173 } | |
174 | |
175 /* Register initialised to Fibonacci numbers */ | |
176 c->R[0] = 1; | |
177 c->R[1] = 1; | |
178 for (i = 2; i < N; ++i) { | |
179 c->R[i] = c->R[i-1] + c->R[i-2]; | |
180 } | |
181 c->konst = INITKONST; | |
182 | |
183 for (i = 0; i < keylen; i += 4) { | |
184 k = BYTE2WORD((unsigned char *)&key[i]); | |
185 ADDKEY(k); | |
186 cycle(c->R); | |
187 XORNL(nltap(c)); | |
188 } | |
189 | |
190 /* also fold in the length of the key */ | |
191 ADDKEY(keylen); | |
192 | |
193 /* now diffuse */ | |
194 s128_diffuse(c); | |
195 s128_genkonst(c); | |
196 s128_savestate(c); | |
197 c->nbuf = 0; | |
198 | |
199 return CRYPT_OK; | |
200 } | |
201 | |
202 /** | |
203 Set IV to the Sober128 state | |
204 @param c The Sober12820 state | |
205 @param iv The IV data to add | |
206 @param ivlen The length of the IV (must be 12) | |
207 @return CRYPT_OK on success | |
208 */ | |
209 int sober128_stream_setiv(sober128_state *c, const unsigned char *iv, unsigned long ivlen) | |
210 { | |
211 ulong32 i, k; | |
212 | |
213 LTC_ARGCHK(c != NULL); | |
214 LTC_ARGCHK(iv != NULL); | |
215 LTC_ARGCHK(ivlen > 0); | |
216 | |
217 /* ok we are adding an IV then... */ | |
218 s128_reloadstate(c); | |
219 | |
220 /* ivlen must be multiple of 4 bytes */ | |
221 if ((ivlen & 3) != 0) { | |
222 return CRYPT_INVALID_KEYSIZE; | |
223 } | |
224 | |
225 for (i = 0; i < ivlen; i += 4) { | |
226 k = BYTE2WORD((unsigned char *)&iv[i]); | |
227 ADDKEY(k); | |
228 cycle(c->R); | |
229 XORNL(nltap(c)); | |
230 } | |
231 | |
232 /* also fold in the length of the key */ | |
233 ADDKEY(ivlen); | |
234 | |
235 /* now diffuse */ | |
236 s128_diffuse(c); | |
237 c->nbuf = 0; | |
238 | |
239 return CRYPT_OK; | |
240 } | |
241 | |
242 /* XOR pseudo-random bytes into buffer | |
243 */ | |
244 #define SROUND(z) STEP(c->R,z); NLFUNC(c,(z+1)); XORWORD(t, in+(z*4), out+(z*4)); | |
245 | |
246 /** | |
247 Encrypt (or decrypt) bytes of ciphertext (or plaintext) with Sober128 | |
248 @param c The Sober128 state | |
249 @param in The plaintext (or ciphertext) | |
250 @param inlen The length of the input (octets) | |
251 @param out [out] The ciphertext (or plaintext), length inlen | |
252 @return CRYPT_OK if successful | |
253 */ | |
254 int sober128_stream_crypt(sober128_state *c, const unsigned char *in, unsigned long inlen, unsigned char *out) | |
255 { | |
256 ulong32 t; | |
257 | |
258 if (inlen == 0) return CRYPT_OK; /* nothing to do */ | |
259 LTC_ARGCHK(out != NULL); | |
260 LTC_ARGCHK(c != NULL); | |
261 | |
262 /* handle any previously buffered bytes */ | |
263 while (c->nbuf != 0 && inlen != 0) { | |
264 *out++ = *in++ ^ (unsigned char)(c->sbuf & 0xFF); | |
265 c->sbuf >>= 8; | |
266 c->nbuf -= 8; | |
267 --inlen; | |
268 } | |
269 | |
270 #ifndef LTC_SMALL_CODE | |
271 /* do lots at a time, if there's enough to do */ | |
272 while (inlen >= N*4) { | |
273 SROUND(0); | |
274 SROUND(1); | |
275 SROUND(2); | |
276 SROUND(3); | |
277 SROUND(4); | |
278 SROUND(5); | |
279 SROUND(6); | |
280 SROUND(7); | |
281 SROUND(8); | |
282 SROUND(9); | |
283 SROUND(10); | |
284 SROUND(11); | |
285 SROUND(12); | |
286 SROUND(13); | |
287 SROUND(14); | |
288 SROUND(15); | |
289 SROUND(16); | |
290 out += 4*N; | |
291 in += 4*N; | |
292 inlen -= 4*N; | |
293 } | |
294 #endif | |
295 | |
296 /* do small or odd size buffers the slow way */ | |
297 while (4 <= inlen) { | |
298 cycle(c->R); | |
299 t = nltap(c); | |
300 XORWORD(t, in, out); | |
301 out += 4; | |
302 in += 4; | |
303 inlen -= 4; | |
304 } | |
305 | |
306 /* handle any trailing bytes */ | |
307 if (inlen != 0) { | |
308 cycle(c->R); | |
309 c->sbuf = nltap(c); | |
310 c->nbuf = 32; | |
311 while (c->nbuf != 0 && inlen != 0) { | |
312 *out++ = *in++ ^ (unsigned char)(c->sbuf & 0xFF); | |
313 c->sbuf >>= 8; | |
314 c->nbuf -= 8; | |
315 --inlen; | |
316 } | |
317 } | |
318 | |
319 return CRYPT_OK; | |
320 } | |
321 | |
322 int sober128_stream_keystream(sober128_state *c, unsigned char *out, unsigned long outlen) | |
323 { | |
324 if (outlen == 0) return CRYPT_OK; /* nothing to do */ | |
325 LTC_ARGCHK(out != NULL); | |
326 XMEMSET(out, 0, outlen); | |
327 return sober128_stream_crypt(c, out, outlen, out); | |
328 } | |
329 | |
330 /** | |
331 Terminate and clear Sober128 state | |
332 @param c The Sober128 state | |
333 @return CRYPT_OK on success | |
334 */ | |
335 int sober128_stream_done(sober128_state *c) | |
336 { | |
337 LTC_ARGCHK(c != NULL); | |
338 XMEMSET(c, 0, sizeof(sober128_state)); | |
339 return CRYPT_OK; | |
340 } | |
341 | |
342 #endif | |
343 | |
344 /* ref: $Format:%D$ */ | |
345 /* git commit: $Format:%H$ */ | |
346 /* commit time: $Format:%ai$ */ |