1 // SPDX-License-Identifier: BSD-2-Clause
2 /* LibTomCrypt, modular cryptographic library -- Tom St Denis
3 *
4 * LibTomCrypt is a library that provides various cryptographic
5 * algorithms in a highly modular and flexible manner.
6 *
7 * The library is free for all purposes without any express
8 * guarantee it works.
9 */
10
11 /*******************************************************************************
12 *
13 * FILE: safer.c
14 *
15 * LTC_DESCRIPTION: block-cipher algorithm LTC_SAFER (Secure And Fast Encryption
16 * Routine) in its four versions: LTC_SAFER K-64, LTC_SAFER K-128,
17 * LTC_SAFER SK-64 and LTC_SAFER SK-128.
18 *
19 * AUTHOR: Richard De Moliner (demoliner@isi.ee.ethz.ch)
20 * Signal and Information Processing Laboratory
21 * Swiss Federal Institute of Technology
22 * CH-8092 Zuerich, Switzerland
23 *
24 * DATE: September 9, 1995
25 *
26 * CHANGE HISTORY:
27 *
28 *******************************************************************************/
29
30 #include "tomcrypt_private.h"
31
32 #ifdef LTC_SAFER
33
34 #define __LTC_SAFER_TAB_C__
35 #include "safer_tab.c"
36
37 const struct ltc_cipher_descriptor safer_k64_desc = {
38 "safer-k64",
39 8, 8, 8, 8, LTC_SAFER_K64_DEFAULT_NOF_ROUNDS,
40 &safer_k64_setup,
41 &safer_ecb_encrypt,
42 &safer_ecb_decrypt,
43 &safer_k64_test,
44 &safer_done,
45 &safer_64_keysize,
46 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
47 },
48
49 safer_sk64_desc = {
50 "safer-sk64",
51 9, 8, 8, 8, LTC_SAFER_SK64_DEFAULT_NOF_ROUNDS,
52 &safer_sk64_setup,
53 &safer_ecb_encrypt,
54 &safer_ecb_decrypt,
55 &safer_sk64_test,
56 &safer_done,
57 &safer_64_keysize,
58 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
59 },
60
61 safer_k128_desc = {
62 "safer-k128",
63 10, 16, 16, 8, LTC_SAFER_K128_DEFAULT_NOF_ROUNDS,
64 &safer_k128_setup,
65 &safer_ecb_encrypt,
66 &safer_ecb_decrypt,
67 &safer_sk128_test,
68 &safer_done,
69 &safer_128_keysize,
70 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
71 },
72
73 safer_sk128_desc = {
74 "safer-sk128",
75 11, 16, 16, 8, LTC_SAFER_SK128_DEFAULT_NOF_ROUNDS,
76 &safer_sk128_setup,
77 &safer_ecb_encrypt,
78 &safer_ecb_decrypt,
79 &safer_sk128_test,
80 &safer_done,
81 &safer_128_keysize,
82 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
83 };
84
85 /******************* Constants ************************************************/
86 /* #define TAB_LEN 256 */
87
88 /******************* Assertions ***********************************************/
89
90 /******************* Macros ***************************************************/
91 #define ROL8(x, n) ((unsigned char)((unsigned int)(x) << (n)\
92 |(unsigned int)((x) & 0xFF) >> (8 - (n))))
93 #define EXP(x) safer_ebox[(x) & 0xFF]
94 #define LOG(x) safer_lbox[(x) & 0xFF]
95 #define PHT(x, y) { y += x; x += y; }
96 #define IPHT(x, y) { x -= y; y -= x; }
97
98 /******************* Types ****************************************************/
99
100 #ifdef LTC_CLEAN_STACK
_Safer_Expand_Userkey(const unsigned char * userkey_1,const unsigned char * userkey_2,unsigned int nof_rounds,int strengthened,safer_key_t key)101 static void _Safer_Expand_Userkey(const unsigned char *userkey_1,
102 const unsigned char *userkey_2,
103 unsigned int nof_rounds,
104 int strengthened,
105 safer_key_t key)
106 #else
107 static void Safer_Expand_Userkey(const unsigned char *userkey_1,
108 const unsigned char *userkey_2,
109 unsigned int nof_rounds,
110 int strengthened,
111 safer_key_t key)
112 #endif
113 { unsigned int i, j, k;
114 unsigned char ka[LTC_SAFER_BLOCK_LEN + 1];
115 unsigned char kb[LTC_SAFER_BLOCK_LEN + 1];
116
117 if (LTC_SAFER_MAX_NOF_ROUNDS < nof_rounds) {
118 nof_rounds = LTC_SAFER_MAX_NOF_ROUNDS;
119 }
120 *key++ = (unsigned char)nof_rounds;
121 ka[LTC_SAFER_BLOCK_LEN] = (unsigned char)0;
122 kb[LTC_SAFER_BLOCK_LEN] = (unsigned char)0;
123 k = 0;
124 for (j = 0; j < LTC_SAFER_BLOCK_LEN; j++) {
125 ka[j] = ROL8(userkey_1[j], 5);
126 ka[LTC_SAFER_BLOCK_LEN] ^= ka[j];
127 kb[j] = *key++ = userkey_2[j];
128 kb[LTC_SAFER_BLOCK_LEN] ^= kb[j];
129 }
130 for (i = 1; i <= nof_rounds; i++) {
131 for (j = 0; j < LTC_SAFER_BLOCK_LEN + 1; j++) {
132 ka[j] = ROL8(ka[j], 6);
133 kb[j] = ROL8(kb[j], 6);
134 }
135 if (strengthened) {
136 k = 2 * i - 1;
137 while (k >= (LTC_SAFER_BLOCK_LEN + 1)) { k -= LTC_SAFER_BLOCK_LEN + 1; }
138 }
139 for (j = 0; j < LTC_SAFER_BLOCK_LEN; j++) {
140 if (strengthened) {
141 *key++ = (ka[k]
142 + safer_ebox[(int)safer_ebox[(int)((18 * i + j + 1)&0xFF)]]) & 0xFF;
143 if (++k == (LTC_SAFER_BLOCK_LEN + 1)) { k = 0; }
144 } else {
145 *key++ = (ka[j] + safer_ebox[(int)safer_ebox[(int)((18 * i + j + 1)&0xFF)]]) & 0xFF;
146 }
147 }
148 if (strengthened) {
149 k = 2 * i;
150 while (k >= (LTC_SAFER_BLOCK_LEN + 1)) { k -= LTC_SAFER_BLOCK_LEN + 1; }
151 }
152 for (j = 0; j < LTC_SAFER_BLOCK_LEN; j++) {
153 if (strengthened) {
154 *key++ = (kb[k]
155 + safer_ebox[(int)safer_ebox[(int)((18 * i + j + 10)&0xFF)]]) & 0xFF;
156 if (++k == (LTC_SAFER_BLOCK_LEN + 1)) { k = 0; }
157 } else {
158 *key++ = (kb[j] + safer_ebox[(int)safer_ebox[(int)((18 * i + j + 10)&0xFF)]]) & 0xFF;
159 }
160 }
161 }
162
163 #ifdef LTC_CLEAN_STACK
164 zeromem(ka, sizeof(ka));
165 zeromem(kb, sizeof(kb));
166 #endif
167 }
168
169 #ifdef LTC_CLEAN_STACK
Safer_Expand_Userkey(const unsigned char * userkey_1,const unsigned char * userkey_2,unsigned int nof_rounds,int strengthened,safer_key_t key)170 static void Safer_Expand_Userkey(const unsigned char *userkey_1,
171 const unsigned char *userkey_2,
172 unsigned int nof_rounds,
173 int strengthened,
174 safer_key_t key)
175 {
176 _Safer_Expand_Userkey(userkey_1, userkey_2, nof_rounds, strengthened, key);
177 burn_stack(sizeof(unsigned char) * (2 * (LTC_SAFER_BLOCK_LEN + 1)) + sizeof(unsigned int)*2);
178 }
179 #endif
180
safer_k64_setup(const unsigned char * key,int keylen,int num_rounds,symmetric_key * skey)181 int safer_k64_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey)
182 {
183 LTC_ARGCHK(key != NULL);
184 LTC_ARGCHK(skey != NULL);
185
186 if (num_rounds != 0 && (num_rounds < 6 || num_rounds > LTC_SAFER_MAX_NOF_ROUNDS)) {
187 return CRYPT_INVALID_ROUNDS;
188 }
189
190 if (keylen != 8) {
191 return CRYPT_INVALID_KEYSIZE;
192 }
193
194 Safer_Expand_Userkey(key, key, (unsigned int)(num_rounds != 0 ?num_rounds:LTC_SAFER_K64_DEFAULT_NOF_ROUNDS), 0, skey->safer.key);
195 return CRYPT_OK;
196 }
197
safer_sk64_setup(const unsigned char * key,int keylen,int num_rounds,symmetric_key * skey)198 int safer_sk64_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey)
199 {
200 LTC_ARGCHK(key != NULL);
201 LTC_ARGCHK(skey != NULL);
202
203 if (num_rounds != 0 && (num_rounds < 6 || num_rounds > LTC_SAFER_MAX_NOF_ROUNDS)) {
204 return CRYPT_INVALID_ROUNDS;
205 }
206
207 if (keylen != 8) {
208 return CRYPT_INVALID_KEYSIZE;
209 }
210
211 Safer_Expand_Userkey(key, key, (unsigned int)(num_rounds != 0 ?num_rounds:LTC_SAFER_SK64_DEFAULT_NOF_ROUNDS), 1, skey->safer.key);
212 return CRYPT_OK;
213 }
214
safer_k128_setup(const unsigned char * key,int keylen,int num_rounds,symmetric_key * skey)215 int safer_k128_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey)
216 {
217 LTC_ARGCHK(key != NULL);
218 LTC_ARGCHK(skey != NULL);
219
220 if (num_rounds != 0 && (num_rounds < 6 || num_rounds > LTC_SAFER_MAX_NOF_ROUNDS)) {
221 return CRYPT_INVALID_ROUNDS;
222 }
223
224 if (keylen != 16) {
225 return CRYPT_INVALID_KEYSIZE;
226 }
227
228 Safer_Expand_Userkey(key, key+8, (unsigned int)(num_rounds != 0 ?num_rounds:LTC_SAFER_K128_DEFAULT_NOF_ROUNDS), 0, skey->safer.key);
229 return CRYPT_OK;
230 }
231
safer_sk128_setup(const unsigned char * key,int keylen,int num_rounds,symmetric_key * skey)232 int safer_sk128_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey)
233 {
234 LTC_ARGCHK(key != NULL);
235 LTC_ARGCHK(skey != NULL);
236
237 if (num_rounds != 0 && (num_rounds < 6 || num_rounds > LTC_SAFER_MAX_NOF_ROUNDS)) {
238 return CRYPT_INVALID_ROUNDS;
239 }
240
241 if (keylen != 16) {
242 return CRYPT_INVALID_KEYSIZE;
243 }
244
245 Safer_Expand_Userkey(key, key+8, (unsigned int)(num_rounds != 0?num_rounds:LTC_SAFER_SK128_DEFAULT_NOF_ROUNDS), 1, skey->safer.key);
246 return CRYPT_OK;
247 }
248
249 #ifdef LTC_CLEAN_STACK
_safer_ecb_encrypt(const unsigned char * pt,unsigned char * ct,const symmetric_key * skey)250 static int _safer_ecb_encrypt(const unsigned char *pt,
251 unsigned char *ct,
252 const symmetric_key *skey)
253 #else
254 int safer_ecb_encrypt(const unsigned char *pt,
255 unsigned char *ct,
256 const symmetric_key *skey)
257 #endif
258 { unsigned char a, b, c, d, e, f, g, h, t;
259 unsigned int round;
260 const unsigned char *key;
261
262 LTC_ARGCHK(pt != NULL);
263 LTC_ARGCHK(ct != NULL);
264 LTC_ARGCHK(skey != NULL);
265
266 key = skey->safer.key;
267 a = pt[0]; b = pt[1]; c = pt[2]; d = pt[3];
268 e = pt[4]; f = pt[5]; g = pt[6]; h = pt[7];
269 if (LTC_SAFER_MAX_NOF_ROUNDS < (round = *key)) round = LTC_SAFER_MAX_NOF_ROUNDS;
270 while(round-- > 0)
271 {
272 a ^= *++key; b += *++key; c += *++key; d ^= *++key;
273 e ^= *++key; f += *++key; g += *++key; h ^= *++key;
274 a = EXP(a) + *++key; b = LOG(b) ^ *++key;
275 c = LOG(c) ^ *++key; d = EXP(d) + *++key;
276 e = EXP(e) + *++key; f = LOG(f) ^ *++key;
277 g = LOG(g) ^ *++key; h = EXP(h) + *++key;
278 PHT(a, b); PHT(c, d); PHT(e, f); PHT(g, h);
279 PHT(a, c); PHT(e, g); PHT(b, d); PHT(f, h);
280 PHT(a, e); PHT(b, f); PHT(c, g); PHT(d, h);
281 t = b; b = e; e = c; c = t; t = d; d = f; f = g; g = t;
282 }
283 a ^= *++key; b += *++key; c += *++key; d ^= *++key;
284 e ^= *++key; f += *++key; g += *++key; h ^= *++key;
285 ct[0] = a & 0xFF; ct[1] = b & 0xFF;
286 ct[2] = c & 0xFF; ct[3] = d & 0xFF;
287 ct[4] = e & 0xFF; ct[5] = f & 0xFF;
288 ct[6] = g & 0xFF; ct[7] = h & 0xFF;
289 return CRYPT_OK;
290 }
291
292 #ifdef LTC_CLEAN_STACK
safer_ecb_encrypt(const unsigned char * pt,unsigned char * ct,const symmetric_key * skey)293 int safer_ecb_encrypt(const unsigned char *pt,
294 unsigned char *ct,
295 const symmetric_key *skey)
296 {
297 int err = _safer_ecb_encrypt(pt, ct, skey);
298 burn_stack(sizeof(unsigned char) * 9 + sizeof(unsigned int) + sizeof(unsigned char *));
299 return err;
300 }
301 #endif
302
303 #ifdef LTC_CLEAN_STACK
_safer_ecb_decrypt(const unsigned char * ct,unsigned char * pt,const symmetric_key * skey)304 static int _safer_ecb_decrypt(const unsigned char *ct,
305 unsigned char *pt,
306 const symmetric_key *skey)
307 #else
308 int safer_ecb_decrypt(const unsigned char *ct,
309 unsigned char *pt,
310 const symmetric_key *skey)
311 #endif
312 { unsigned char a, b, c, d, e, f, g, h, t;
313 unsigned int round;
314 const unsigned char *key;
315
316 LTC_ARGCHK(ct != NULL);
317 LTC_ARGCHK(pt != NULL);
318 LTC_ARGCHK(skey != NULL);
319
320 key = skey->safer.key;
321 a = ct[0]; b = ct[1]; c = ct[2]; d = ct[3];
322 e = ct[4]; f = ct[5]; g = ct[6]; h = ct[7];
323 if (LTC_SAFER_MAX_NOF_ROUNDS < (round = *key)) round = LTC_SAFER_MAX_NOF_ROUNDS;
324 key += LTC_SAFER_BLOCK_LEN * (1 + 2 * round);
325 h ^= *key; g -= *--key; f -= *--key; e ^= *--key;
326 d ^= *--key; c -= *--key; b -= *--key; a ^= *--key;
327 while (round--)
328 {
329 t = e; e = b; b = c; c = t; t = f; f = d; d = g; g = t;
330 IPHT(a, e); IPHT(b, f); IPHT(c, g); IPHT(d, h);
331 IPHT(a, c); IPHT(e, g); IPHT(b, d); IPHT(f, h);
332 IPHT(a, b); IPHT(c, d); IPHT(e, f); IPHT(g, h);
333 h -= *--key; g ^= *--key; f ^= *--key; e -= *--key;
334 d -= *--key; c ^= *--key; b ^= *--key; a -= *--key;
335 h = LOG(h) ^ *--key; g = EXP(g) - *--key;
336 f = EXP(f) - *--key; e = LOG(e) ^ *--key;
337 d = LOG(d) ^ *--key; c = EXP(c) - *--key;
338 b = EXP(b) - *--key; a = LOG(a) ^ *--key;
339 }
340 pt[0] = a & 0xFF; pt[1] = b & 0xFF;
341 pt[2] = c & 0xFF; pt[3] = d & 0xFF;
342 pt[4] = e & 0xFF; pt[5] = f & 0xFF;
343 pt[6] = g & 0xFF; pt[7] = h & 0xFF;
344 return CRYPT_OK;
345 }
346
347 #ifdef LTC_CLEAN_STACK
safer_ecb_decrypt(const unsigned char * ct,unsigned char * pt,const symmetric_key * skey)348 int safer_ecb_decrypt(const unsigned char *ct,
349 unsigned char *pt,
350 const symmetric_key *skey)
351 {
352 int err = _safer_ecb_decrypt(ct, pt, skey);
353 burn_stack(sizeof(unsigned char) * 9 + sizeof(unsigned int) + sizeof(unsigned char *));
354 return err;
355 }
356 #endif
357
safer_64_keysize(int * keysize)358 int safer_64_keysize(int *keysize)
359 {
360 LTC_ARGCHK(keysize != NULL);
361 if (*keysize < 8) {
362 return CRYPT_INVALID_KEYSIZE;
363 }
364 *keysize = 8;
365 return CRYPT_OK;
366 }
367
safer_128_keysize(int * keysize)368 int safer_128_keysize(int *keysize)
369 {
370 LTC_ARGCHK(keysize != NULL);
371 if (*keysize < 16) {
372 return CRYPT_INVALID_KEYSIZE;
373 }
374 *keysize = 16;
375 return CRYPT_OK;
376 }
377
safer_k64_test(void)378 int safer_k64_test(void)
379 {
380 #ifndef LTC_TEST
381 return CRYPT_NOP;
382 #else
383 static const unsigned char k64_pt[] = { 1, 2, 3, 4, 5, 6, 7, 8 },
384 k64_key[] = { 8, 7, 6, 5, 4, 3, 2, 1 },
385 k64_ct[] = { 200, 242, 156, 221, 135, 120, 62, 217 };
386
387 symmetric_key skey;
388 unsigned char buf[2][8];
389 int err;
390
391 /* test K64 */
392 if ((err = safer_k64_setup(k64_key, 8, 6, &skey)) != CRYPT_OK) {
393 return err;
394 }
395 safer_ecb_encrypt(k64_pt, buf[0], &skey);
396 safer_ecb_decrypt(buf[0], buf[1], &skey);
397
398 if (compare_testvector(buf[0], 8, k64_ct, 8, "Safer K64 Encrypt", 0) != 0 ||
399 compare_testvector(buf[1], 8, k64_pt, 8, "Safer K64 Decrypt", 0) != 0) {
400 return CRYPT_FAIL_TESTVECTOR;
401 }
402
403 return CRYPT_OK;
404 #endif
405 }
406
407
safer_sk64_test(void)408 int safer_sk64_test(void)
409 {
410 #ifndef LTC_TEST
411 return CRYPT_NOP;
412 #else
413 static const unsigned char sk64_pt[] = { 1, 2, 3, 4, 5, 6, 7, 8 },
414 sk64_key[] = { 1, 2, 3, 4, 5, 6, 7, 8 },
415 sk64_ct[] = { 95, 206, 155, 162, 5, 132, 56, 199 };
416
417 symmetric_key skey;
418 unsigned char buf[2][8];
419 int err, y;
420
421 /* test SK64 */
422 if ((err = safer_sk64_setup(sk64_key, 8, 6, &skey)) != CRYPT_OK) {
423 return err;
424 }
425
426 safer_ecb_encrypt(sk64_pt, buf[0], &skey);
427 safer_ecb_decrypt(buf[0], buf[1], &skey);
428
429 if (compare_testvector(buf[0], 8, sk64_ct, 8, "Safer SK64 Encrypt", 0) != 0 ||
430 compare_testvector(buf[1], 8, sk64_pt, 8, "Safer SK64 Decrypt", 0) != 0) {
431 return CRYPT_FAIL_TESTVECTOR;
432 }
433
434 /* now see if we can encrypt all zero bytes 1000 times, decrypt and come back where we started */
435 for (y = 0; y < 8; y++) buf[0][y] = 0;
436 for (y = 0; y < 1000; y++) safer_ecb_encrypt(buf[0], buf[0], &skey);
437 for (y = 0; y < 1000; y++) safer_ecb_decrypt(buf[0], buf[0], &skey);
438 for (y = 0; y < 8; y++) if (buf[0][y] != 0) return CRYPT_FAIL_TESTVECTOR;
439
440 return CRYPT_OK;
441 #endif
442 }
443
444 /** Terminate the context
445 @param skey The scheduled key
446 */
safer_done(symmetric_key * skey)447 void safer_done(symmetric_key *skey)
448 {
449 LTC_UNUSED_PARAM(skey);
450 }
451
safer_sk128_test(void)452 int safer_sk128_test(void)
453 {
454 #ifndef LTC_TEST
455 return CRYPT_NOP;
456 #else
457 static const unsigned char sk128_pt[] = { 1, 2, 3, 4, 5, 6, 7, 8 },
458 sk128_key[] = { 1, 2, 3, 4, 5, 6, 7, 8,
459 0, 0, 0, 0, 0, 0, 0, 0 },
460 sk128_ct[] = { 255, 120, 17, 228, 179, 167, 46, 113 };
461
462 symmetric_key skey;
463 unsigned char buf[2][8];
464 int err, y;
465
466 /* test SK128 */
467 if ((err = safer_sk128_setup(sk128_key, 16, 0, &skey)) != CRYPT_OK) {
468 return err;
469 }
470 safer_ecb_encrypt(sk128_pt, buf[0], &skey);
471 safer_ecb_decrypt(buf[0], buf[1], &skey);
472
473 if (compare_testvector(buf[0], 8, sk128_ct, 8, "Safer SK128 Encrypt", 0) != 0 ||
474 compare_testvector(buf[1], 8, sk128_pt, 8, "Safer SK128 Decrypt", 0) != 0) {
475 return CRYPT_FAIL_TESTVECTOR;
476 }
477
478 /* now see if we can encrypt all zero bytes 1000 times, decrypt and come back where we started */
479 for (y = 0; y < 8; y++) buf[0][y] = 0;
480 for (y = 0; y < 1000; y++) safer_ecb_encrypt(buf[0], buf[0], &skey);
481 for (y = 0; y < 1000; y++) safer_ecb_decrypt(buf[0], buf[0], &skey);
482 for (y = 0; y < 8; y++) if (buf[0][y] != 0) return CRYPT_FAIL_TESTVECTOR;
483
484 return CRYPT_OK;
485 #endif
486 }
487
488 #endif
489
490
491
492
493 /* ref: $Format:%D$ */
494 /* git commit: $Format:%H$ */
495 /* commit time: $Format:%ai$ */
496