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 * Tom St Denis, tomstdenis@gmail.com, http://libtomcrypt.com
10 */
11
12/**
13   @file saferp.c
14   SAFER+ Implementation by Tom St Denis
15*/
16#include "tomcrypt.h"
17
18#ifdef SAFERP
19
20const struct ltc_cipher_descriptor saferp_desc =
21{
22    "safer+",
23    4,
24    16, 32, 16, 8,
25    &saferp_setup,
26    &saferp_ecb_encrypt,
27    &saferp_ecb_decrypt,
28    &saferp_test,
29    &saferp_done,
30    &saferp_keysize,
31    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
32};
33
34/* ROUND(b,i)
35 *
36 * This is one forward key application.  Note the basic form is
37 * key addition, substitution, key addition.  The safer_ebox and safer_lbox
38 * are the exponentiation box and logarithm boxes respectively.
39 * The value of 'i' is the current round number which allows this
40 * function to be unrolled massively.  Most of SAFER+'s speed
41 * comes from not having to compute indirect accesses into the
42 * array of 16 bytes b[0..15] which is the block of data
43*/
44
45extern const unsigned char safer_ebox[], safer_lbox[];
46
47#define ROUND(b, i)                                                                        \
48    b[0]  = (safer_ebox[(b[0] ^ skey->saferp.K[i][0]) & 255] + skey->saferp.K[i+1][0]) & 255;    \
49    b[1]  = safer_lbox[(b[1] + skey->saferp.K[i][1]) & 255] ^ skey->saferp.K[i+1][1];            \
50    b[2]  = safer_lbox[(b[2] + skey->saferp.K[i][2]) & 255] ^ skey->saferp.K[i+1][2];            \
51    b[3]  = (safer_ebox[(b[3] ^ skey->saferp.K[i][3]) & 255] + skey->saferp.K[i+1][3]) & 255;    \
52    b[4]  = (safer_ebox[(b[4] ^ skey->saferp.K[i][4]) & 255] + skey->saferp.K[i+1][4]) & 255;    \
53    b[5]  = safer_lbox[(b[5] + skey->saferp.K[i][5]) & 255] ^ skey->saferp.K[i+1][5];            \
54    b[6]  = safer_lbox[(b[6] + skey->saferp.K[i][6]) & 255] ^ skey->saferp.K[i+1][6];            \
55    b[7]  = (safer_ebox[(b[7] ^ skey->saferp.K[i][7]) & 255] + skey->saferp.K[i+1][7]) & 255;    \
56    b[8]  = (safer_ebox[(b[8] ^ skey->saferp.K[i][8]) & 255] + skey->saferp.K[i+1][8]) & 255;    \
57    b[9]  = safer_lbox[(b[9] + skey->saferp.K[i][9]) & 255] ^ skey->saferp.K[i+1][9];            \
58    b[10] = safer_lbox[(b[10] + skey->saferp.K[i][10]) & 255] ^ skey->saferp.K[i+1][10];         \
59    b[11] = (safer_ebox[(b[11] ^ skey->saferp.K[i][11]) & 255] + skey->saferp.K[i+1][11]) & 255; \
60    b[12] = (safer_ebox[(b[12] ^ skey->saferp.K[i][12]) & 255] + skey->saferp.K[i+1][12]) & 255; \
61    b[13] = safer_lbox[(b[13] + skey->saferp.K[i][13]) & 255] ^ skey->saferp.K[i+1][13];         \
62    b[14] = safer_lbox[(b[14] + skey->saferp.K[i][14]) & 255] ^ skey->saferp.K[i+1][14];         \
63    b[15] = (safer_ebox[(b[15] ^ skey->saferp.K[i][15]) & 255] + skey->saferp.K[i+1][15]) & 255;
64
65/* This is one inverse key application */
66#define iROUND(b, i)                                                                       \
67    b[0]  = safer_lbox[(b[0] - skey->saferp.K[i+1][0]) & 255] ^ skey->saferp.K[i][0];            \
68    b[1]  = (safer_ebox[(b[1] ^ skey->saferp.K[i+1][1]) & 255] - skey->saferp.K[i][1]) & 255;    \
69    b[2]  = (safer_ebox[(b[2] ^ skey->saferp.K[i+1][2]) & 255] - skey->saferp.K[i][2]) & 255;    \
70    b[3]  = safer_lbox[(b[3] - skey->saferp.K[i+1][3]) & 255] ^ skey->saferp.K[i][3];            \
71    b[4]  = safer_lbox[(b[4] - skey->saferp.K[i+1][4]) & 255] ^ skey->saferp.K[i][4];            \
72    b[5]  = (safer_ebox[(b[5] ^ skey->saferp.K[i+1][5]) & 255] - skey->saferp.K[i][5]) & 255;    \
73    b[6]  = (safer_ebox[(b[6] ^ skey->saferp.K[i+1][6]) & 255] - skey->saferp.K[i][6]) & 255;    \
74    b[7]  = safer_lbox[(b[7] - skey->saferp.K[i+1][7]) & 255] ^ skey->saferp.K[i][7];            \
75    b[8]  = safer_lbox[(b[8] - skey->saferp.K[i+1][8]) & 255] ^ skey->saferp.K[i][8];            \
76    b[9]  = (safer_ebox[(b[9] ^ skey->saferp.K[i+1][9]) & 255] - skey->saferp.K[i][9]) & 255;    \
77    b[10] = (safer_ebox[(b[10] ^ skey->saferp.K[i+1][10]) & 255] - skey->saferp.K[i][10]) & 255; \
78    b[11] = safer_lbox[(b[11] - skey->saferp.K[i+1][11]) & 255] ^ skey->saferp.K[i][11];         \
79    b[12] = safer_lbox[(b[12] - skey->saferp.K[i+1][12]) & 255] ^ skey->saferp.K[i][12];         \
80    b[13] = (safer_ebox[(b[13] ^ skey->saferp.K[i+1][13]) & 255] - skey->saferp.K[i][13]) & 255; \
81    b[14] = (safer_ebox[(b[14] ^ skey->saferp.K[i+1][14]) & 255] - skey->saferp.K[i][14]) & 255; \
82    b[15] = safer_lbox[(b[15] - skey->saferp.K[i+1][15]) & 255] ^ skey->saferp.K[i][15];
83
84/* This is a forward single layer PHT transform.  */
85#define PHT(b)                                               \
86    b[0]  = (b[0] + (b[1] = (b[0] + b[1]) & 255)) & 255;     \
87    b[2]  = (b[2] + (b[3] = (b[3] + b[2]) & 255)) & 255;     \
88    b[4]  = (b[4] + (b[5] = (b[5] + b[4]) & 255)) & 255;     \
89    b[6]  = (b[6] + (b[7] = (b[7] + b[6]) & 255)) & 255;     \
90    b[8]  = (b[8] + (b[9] = (b[9] + b[8]) & 255)) & 255;     \
91    b[10] = (b[10] + (b[11] = (b[11] + b[10]) & 255)) & 255; \
92    b[12] = (b[12] + (b[13] = (b[13] + b[12]) & 255)) & 255; \
93    b[14] = (b[14] + (b[15] = (b[15] + b[14]) & 255)) & 255;
94
95/* This is an inverse single layer PHT transform */
96#define iPHT(b)                                               \
97    b[15] = (b[15] - (b[14] = (b[14] - b[15]) & 255)) & 255;  \
98    b[13] = (b[13] - (b[12] = (b[12] - b[13]) & 255)) & 255;  \
99    b[11] = (b[11] - (b[10] = (b[10] - b[11]) & 255)) & 255;  \
100    b[9]  = (b[9] - (b[8] = (b[8] - b[9]) & 255)) & 255;      \
101    b[7]  = (b[7] - (b[6] = (b[6] - b[7]) & 255)) & 255;      \
102    b[5]  = (b[5] - (b[4] = (b[4] - b[5]) & 255)) & 255;      \
103    b[3]  = (b[3] - (b[2] = (b[2] - b[3]) & 255)) & 255;      \
104    b[1]  = (b[1] - (b[0] = (b[0] - b[1]) & 255)) & 255;      \
105
106/* This is the "Armenian" Shuffle.  It takes the input from b and stores it in b2 */
107#define SHUF(b, b2)                                              \
108    b2[0] = b[8]; b2[1] = b[11]; b2[2] = b[12]; b2[3] = b[15];   \
109    b2[4] = b[2]; b2[5] = b[1]; b2[6] = b[6]; b2[7] = b[5];      \
110    b2[8] = b[10]; b2[9] = b[9]; b2[10] = b[14]; b2[11] = b[13]; \
111    b2[12] = b[0]; b2[13] = b[7]; b2[14] = b[4]; b2[15] = b[3];
112
113/* This is the inverse shuffle.  It takes from b and gives to b2 */
114#define iSHUF(b, b2)                                               \
115    b2[0] = b[12]; b2[1] = b[5]; b2[2] = b[4]; b2[3] = b[15];      \
116    b2[4] = b[14]; b2[5] = b[7]; b2[6] = b[6]; b2[7] = b[13];      \
117    b2[8] = b[0]; b2[9] = b[9]; b2[10] = b[8]; b2[11] = b[1];      \
118    b2[12] = b[2]; b2[13] = b[11]; b2[14] = b[10]; b2[15] = b[3];
119
120/* The complete forward Linear Transform layer.
121 * Note that alternating usage of b and b2.
122 * Each round of LT starts in 'b' and ends in 'b2'.
123 */
124#define LT(b, b2)             \
125    PHT(b);  SHUF(b, b2);     \
126    PHT(b2); SHUF(b2, b);     \
127    PHT(b);  SHUF(b, b2);     \
128    PHT(b2);
129
130/* This is the inverse linear transform layer.  */
131#define iLT(b, b2)            \
132    iPHT(b);                  \
133    iSHUF(b, b2); iPHT(b2);   \
134    iSHUF(b2, b); iPHT(b);    \
135    iSHUF(b, b2); iPHT(b2);
136
137#ifdef LTC_SMALL_CODE
138
139static void _round(unsigned char *b, int i, symmetric_key *skey)
140{
141   ROUND(b, i);
142}
143
144static void _iround(unsigned char *b, int i, symmetric_key *skey)
145{
146   iROUND(b, i);
147}
148
149static void _lt(unsigned char *b, unsigned char *b2)
150{
151   LT(b, b2);
152}
153
154static void _ilt(unsigned char *b, unsigned char *b2)
155{
156   iLT(b, b2);
157}
158
159#undef ROUND
160#define ROUND(b, i) _round(b, i, skey)
161
162#undef iROUND
163#define iROUND(b, i) _iround(b, i, skey)
164
165#undef LT
166#define LT(b, b2) _lt(b, b2)
167
168#undef iLT
169#define iLT(b, b2) _ilt(b, b2)
170
171#endif
172
173/* These are the 33, 128-bit bias words for the key schedule */
174static const unsigned char safer_bias[33][16] = {
175{  70, 151, 177, 186, 163, 183,  16,  10, 197,  55, 179, 201,  90,  40, 172, 100},
176{ 236, 171, 170, 198, 103, 149,  88,  13, 248, 154, 246, 110, 102, 220,   5,  61},
177{ 138, 195, 216, 137, 106, 233,  54,  73,  67, 191, 235, 212, 150, 155, 104, 160},
178{  93,  87, 146,  31, 213, 113,  92, 187,  34, 193, 190, 123, 188, 153,  99, 148},
179{  42,  97, 184,  52,  50,  25, 253, 251,  23,  64, 230,  81,  29,  65,  68, 143},
180{ 221,   4, 128, 222, 231,  49, 214, 127,   1, 162, 247,  57, 218, 111,  35, 202},
181{  58, 208,  28, 209,  48,  62,  18, 161, 205,  15, 224, 168, 175, 130,  89,  44},
182{ 125, 173, 178, 239, 194, 135, 206, 117,   6,  19,   2, 144,  79,  46, 114,  51},
183{ 192, 141, 207, 169, 129, 226, 196,  39,  47, 108, 122, 159,  82, 225,  21,  56},
184{ 252,  32,  66, 199,   8, 228,   9,  85,  94, 140,  20, 118,  96, 255, 223, 215},
185{ 250,  11,  33,   0,  26, 249, 166, 185, 232, 158,  98,  76, 217, 145,  80, 210},
186{  24, 180,   7, 132, 234,  91, 164, 200,  14, 203,  72, 105,  75,  78, 156,  53},
187{  69,  77,  84, 229,  37,  60,  12,  74, 139,  63, 204, 167, 219, 107, 174, 244},
188{  45, 243, 124, 109, 157, 181,  38, 116, 242, 147,  83, 176, 240,  17, 237, 131},
189{ 182,   3,  22, 115,  59,  30, 142, 112, 189, 134,  27,  71, 126,  36,  86, 241},
190{ 136,  70, 151, 177, 186, 163, 183,  16,  10, 197,  55, 179, 201,  90,  40, 172},
191{ 220, 134, 119, 215, 166,  17, 251, 244, 186, 146, 145, 100, 131, 241,  51, 239},
192{  44, 181, 178,  43, 136, 209, 153, 203, 140, 132,  29,  20, 129, 151, 113, 202},
193{ 163, 139,  87,  60, 130, 196,  82,  92,  28, 232, 160,   4, 180, 133,  74, 246},
194{  84, 182, 223,  12,  26, 142, 222, 224,  57, 252,  32, 155,  36,  78, 169, 152},
195{ 171, 242,  96, 208, 108, 234, 250, 199, 217,   0, 212,  31, 110,  67, 188, 236},
196{ 137, 254, 122,  93,  73, 201,  50, 194, 249, 154, 248, 109,  22, 219,  89, 150},
197{ 233, 205, 230,  70,  66, 143,  10, 193, 204, 185, 101, 176, 210, 198, 172,  30},
198{  98,  41,  46,  14, 116,  80,   2,  90, 195,  37, 123, 138,  42,  91, 240,   6},
199{  71, 111, 112, 157, 126,  16, 206,  18,  39, 213,  76,  79, 214, 121,  48, 104},
200{ 117, 125, 228, 237, 128, 106, 144,  55, 162,  94, 118, 170, 197, 127,  61, 175},
201{ 229,  25,  97, 253,  77, 124, 183,  11, 238, 173,  75,  34, 245, 231, 115,  35},
202{ 200,   5, 225, 102, 221, 179,  88, 105,  99,  86,  15, 161,  49, 149,  23,   7},
203{  40,   1,  45, 226, 147, 190,  69,  21, 174, 120,   3, 135, 164, 184,  56, 207},
204{   8, 103,   9, 148, 235,  38, 168, 107, 189,  24,  52,  27, 187, 191, 114, 247},
205{  53,  72, 156,  81,  47,  59,  85, 227, 192, 159, 216, 211, 243, 141, 177, 255},
206{  62, 220, 134, 119, 215, 166,  17, 251, 244, 186, 146, 145, 100, 131, 241,  51}};
207
208 /**
209    Initialize the SAFER+ block cipher
210    @param key The symmetric key you wish to pass
211    @param keylen The key length in bytes
212    @param num_rounds The number of rounds desired (0 for default)
213    @param skey The key in as scheduled by this function.
214    @return CRYPT_OK if successful
215 */
216int saferp_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey)
217{
218   unsigned x, y, z;
219   unsigned char t[33];
220   static const int rounds[3] = { 8, 12, 16 };
221
222   LTC_ARGCHK(key  != NULL);
223   LTC_ARGCHK(skey != NULL);
224
225   /* check arguments */
226   if (keylen != 16 && keylen != 24 && keylen != 32) {
227      return CRYPT_INVALID_KEYSIZE;
228   }
229
230   /* Is the number of rounds valid?  Either use zero for default or
231    * 8,12,16 rounds for 16,24,32 byte keys
232    */
233   if (num_rounds != 0 && num_rounds != rounds[(keylen/8)-2]) {
234      return CRYPT_INVALID_ROUNDS;
235   }
236
237   /* 128 bit key version */
238   if (keylen == 16) {
239       /* copy key into t */
240       for (x = y = 0; x < 16; x++) {
241           t[x] = key[x];
242           y ^= key[x];
243       }
244       t[16] = y;
245
246       /* make round keys */
247       for (x = 0; x < 16; x++) {
248           skey->saferp.K[0][x] = t[x];
249       }
250
251       /* make the 16 other keys as a transformation of the first key */
252       for (x = 1; x < 17; x++) {
253           /* rotate 3 bits each */
254           for (y = 0; y < 17; y++) {
255               t[y] = ((t[y]<<3)|(t[y]>>5)) & 255;
256           }
257
258           /* select and add */
259           z = x;
260           for (y = 0; y < 16; y++) {
261               skey->saferp.K[x][y] = (t[z] + safer_bias[x-1][y]) & 255;
262               if (++z == 17) { z = 0; }
263           }
264       }
265       skey->saferp.rounds = 8;
266   } else if (keylen == 24) {
267       /* copy key into t */
268       for (x = y = 0; x < 24; x++) {
269           t[x] = key[x];
270           y ^= key[x];
271       }
272       t[24] = y;
273
274       /* make round keys */
275       for (x = 0; x < 16; x++) {
276           skey->saferp.K[0][x] = t[x];
277       }
278
279       for (x = 1; x < 25; x++) {
280           /* rotate 3 bits each */
281           for (y = 0; y < 25; y++) {
282               t[y] = ((t[y]<<3)|(t[y]>>5)) & 255;
283           }
284
285           /* select and add */
286           z = x;
287           for (y = 0; y < 16; y++) {
288               skey->saferp.K[x][y] = (t[z] + safer_bias[x-1][y]) & 255;
289               if (++z == 25) { z = 0; }
290           }
291       }
292       skey->saferp.rounds = 12;
293   } else {
294       /* copy key into t */
295       for (x = y = 0; x < 32; x++) {
296           t[x] = key[x];
297           y ^= key[x];
298       }
299       t[32] = y;
300
301       /* make round keys */
302       for (x = 0; x < 16; x++) {
303           skey->saferp.K[0][x] = t[x];
304       }
305
306       for (x = 1; x < 33; x++) {
307           /* rotate 3 bits each */
308           for (y = 0; y < 33; y++) {
309               t[y] = ((t[y]<<3)|(t[y]>>5)) & 255;
310           }
311
312           /* select and add */
313           z = x;
314           for (y = 0; y < 16; y++) {
315               skey->saferp.K[x][y] = (t[z] + safer_bias[x-1][y]) & 255;
316               if (++z == 33) { z = 0; }
317           }
318       }
319       skey->saferp.rounds = 16;
320   }
321#ifdef LTC_CLEAN_STACK
322   zeromem(t, sizeof(t));
323#endif
324   return CRYPT_OK;
325}
326
327/**
328  Encrypts a block of text with SAFER+
329  @param pt The input plaintext (16 bytes)
330  @param ct The output ciphertext (16 bytes)
331  @param skey The key as scheduled
332  @return CRYPT_OK if successful
333*/
334int saferp_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey)
335{
336   unsigned char b[16];
337   int x;
338
339   LTC_ARGCHK(pt   != NULL);
340   LTC_ARGCHK(ct   != NULL);
341   LTC_ARGCHK(skey != NULL);
342
343   /* do eight rounds */
344   for (x = 0; x < 16; x++) {
345       b[x] = pt[x];
346   }
347   ROUND(b,  0);  LT(b, ct);
348   ROUND(ct, 2);  LT(ct, b);
349   ROUND(b,  4);  LT(b, ct);
350   ROUND(ct, 6);  LT(ct, b);
351   ROUND(b,  8);  LT(b, ct);
352   ROUND(ct, 10); LT(ct, b);
353   ROUND(b,  12); LT(b, ct);
354   ROUND(ct, 14); LT(ct, b);
355   /* 192-bit key? */
356   if (skey->saferp.rounds > 8) {
357      ROUND(b, 16);  LT(b, ct);
358      ROUND(ct, 18); LT(ct, b);
359      ROUND(b, 20);  LT(b, ct);
360      ROUND(ct, 22); LT(ct, b);
361   }
362   /* 256-bit key? */
363   if (skey->saferp.rounds > 12) {
364      ROUND(b, 24);  LT(b, ct);
365      ROUND(ct, 26); LT(ct, b);
366      ROUND(b, 28);  LT(b, ct);
367      ROUND(ct, 30); LT(ct, b);
368   }
369   ct[0] = b[0] ^ skey->saferp.K[skey->saferp.rounds*2][0];
370   ct[1] = (b[1] + skey->saferp.K[skey->saferp.rounds*2][1]) & 255;
371   ct[2] = (b[2] + skey->saferp.K[skey->saferp.rounds*2][2]) & 255;
372   ct[3] = b[3] ^ skey->saferp.K[skey->saferp.rounds*2][3];
373   ct[4] = b[4] ^ skey->saferp.K[skey->saferp.rounds*2][4];
374   ct[5] = (b[5] + skey->saferp.K[skey->saferp.rounds*2][5]) & 255;
375   ct[6] = (b[6] + skey->saferp.K[skey->saferp.rounds*2][6]) & 255;
376   ct[7] = b[7] ^ skey->saferp.K[skey->saferp.rounds*2][7];
377   ct[8] = b[8] ^ skey->saferp.K[skey->saferp.rounds*2][8];
378   ct[9] = (b[9] + skey->saferp.K[skey->saferp.rounds*2][9]) & 255;
379   ct[10] = (b[10] + skey->saferp.K[skey->saferp.rounds*2][10]) & 255;
380   ct[11] = b[11] ^ skey->saferp.K[skey->saferp.rounds*2][11];
381   ct[12] = b[12] ^ skey->saferp.K[skey->saferp.rounds*2][12];
382   ct[13] = (b[13] + skey->saferp.K[skey->saferp.rounds*2][13]) & 255;
383   ct[14] = (b[14] + skey->saferp.K[skey->saferp.rounds*2][14]) & 255;
384   ct[15] = b[15] ^ skey->saferp.K[skey->saferp.rounds*2][15];
385#ifdef LTC_CLEAN_STACK
386   zeromem(b, sizeof(b));
387#endif
388   return CRYPT_OK;
389}
390
391/**
392  Decrypts a block of text with SAFER+
393  @param ct The input ciphertext (16 bytes)
394  @param pt The output plaintext (16 bytes)
395  @param skey The key as scheduled
396  @return CRYPT_OK if successful
397*/
398int saferp_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey)
399{
400   unsigned char b[16];
401   int x;
402
403   LTC_ARGCHK(pt   != NULL);
404   LTC_ARGCHK(ct   != NULL);
405   LTC_ARGCHK(skey != NULL);
406
407   /* do eight rounds */
408   b[0] = ct[0] ^ skey->saferp.K[skey->saferp.rounds*2][0];
409   b[1] = (ct[1] - skey->saferp.K[skey->saferp.rounds*2][1]) & 255;
410   b[2] = (ct[2] - skey->saferp.K[skey->saferp.rounds*2][2]) & 255;
411   b[3] = ct[3] ^ skey->saferp.K[skey->saferp.rounds*2][3];
412   b[4] = ct[4] ^ skey->saferp.K[skey->saferp.rounds*2][4];
413   b[5] = (ct[5] - skey->saferp.K[skey->saferp.rounds*2][5]) & 255;
414   b[6] = (ct[6] - skey->saferp.K[skey->saferp.rounds*2][6]) & 255;
415   b[7] = ct[7] ^ skey->saferp.K[skey->saferp.rounds*2][7];
416   b[8] = ct[8] ^ skey->saferp.K[skey->saferp.rounds*2][8];
417   b[9] = (ct[9] - skey->saferp.K[skey->saferp.rounds*2][9]) & 255;
418   b[10] = (ct[10] - skey->saferp.K[skey->saferp.rounds*2][10]) & 255;
419   b[11] = ct[11] ^ skey->saferp.K[skey->saferp.rounds*2][11];
420   b[12] = ct[12] ^ skey->saferp.K[skey->saferp.rounds*2][12];
421   b[13] = (ct[13] - skey->saferp.K[skey->saferp.rounds*2][13]) & 255;
422   b[14] = (ct[14] - skey->saferp.K[skey->saferp.rounds*2][14]) & 255;
423   b[15] = ct[15] ^ skey->saferp.K[skey->saferp.rounds*2][15];
424   /* 256-bit key? */
425   if (skey->saferp.rounds > 12) {
426      iLT(b, pt); iROUND(pt, 30);
427      iLT(pt, b); iROUND(b, 28);
428      iLT(b, pt); iROUND(pt, 26);
429      iLT(pt, b); iROUND(b, 24);
430   }
431   /* 192-bit key? */
432   if (skey->saferp.rounds > 8) {
433      iLT(b, pt); iROUND(pt, 22);
434      iLT(pt, b); iROUND(b, 20);
435      iLT(b, pt); iROUND(pt, 18);
436      iLT(pt, b); iROUND(b, 16);
437   }
438   iLT(b, pt); iROUND(pt, 14);
439   iLT(pt, b); iROUND(b, 12);
440   iLT(b, pt); iROUND(pt,10);
441   iLT(pt, b); iROUND(b, 8);
442   iLT(b, pt); iROUND(pt,6);
443   iLT(pt, b); iROUND(b, 4);
444   iLT(b, pt); iROUND(pt,2);
445   iLT(pt, b); iROUND(b, 0);
446   for (x = 0; x < 16; x++) {
447       pt[x] = b[x];
448   }
449#ifdef LTC_CLEAN_STACK
450   zeromem(b, sizeof(b));
451#endif
452   return CRYPT_OK;
453}
454
455/**
456  Performs a self-test of the SAFER+ block cipher
457  @return CRYPT_OK if functional, CRYPT_NOP if self-test has been disabled
458*/
459int saferp_test(void)
460{
461 #ifndef LTC_TEST
462    return CRYPT_NOP;
463 #else
464   static const struct {
465       int keylen;
466       unsigned char key[32], pt[16], ct[16];
467   } tests[] = {
468       {
469           16,
470           { 41, 35, 190, 132, 225, 108, 214, 174,
471             82, 144, 73, 241, 241, 187, 233, 235 },
472           { 179, 166, 219, 60, 135, 12, 62, 153,
473             36, 94, 13, 28, 6, 183, 71, 222 },
474           { 224, 31, 182, 10, 12, 255, 84, 70,
475             127, 13, 89, 249, 9, 57, 165, 220 }
476       }, {
477           24,
478           { 72, 211, 143, 117, 230, 217, 29, 42,
479             229, 192, 247, 43, 120, 129, 135, 68,
480             14, 95, 80, 0, 212, 97, 141, 190 },
481           { 123, 5, 21, 7, 59, 51, 130, 31,
482             24, 112, 146, 218, 100, 84, 206, 177 },
483           { 92, 136, 4, 63, 57, 95, 100, 0,
484             150, 130, 130, 16, 193, 111, 219, 133 }
485       }, {
486           32,
487           { 243, 168, 141, 254, 190, 242, 235, 113,
488             255, 160, 208, 59, 117, 6, 140, 126,
489             135, 120, 115, 77, 208, 190, 130, 190,
490             219, 194, 70, 65, 43, 140, 250, 48 },
491           { 127, 112, 240, 167, 84, 134, 50, 149,
492             170, 91, 104, 19, 11, 230, 252, 245 },
493           { 88, 11, 25, 36, 172, 229, 202, 213,
494             170, 65, 105, 153, 220, 104, 153, 138 }
495       }
496    };
497
498   unsigned char tmp[2][16];
499   symmetric_key skey;
500   int err, i, y;
501
502   for (i = 0; i < (int)(sizeof(tests) / sizeof(tests[0])); i++) {
503      if ((err = saferp_setup(tests[i].key, tests[i].keylen, 0, &skey)) != CRYPT_OK)  {
504         return err;
505      }
506      saferp_ecb_encrypt(tests[i].pt, tmp[0], &skey);
507      saferp_ecb_decrypt(tmp[0], tmp[1], &skey);
508
509      /* compare */
510      if (XMEMCMP(tmp[0], tests[i].ct, 16) || XMEMCMP(tmp[1], tests[i].pt, 16)) {
511         return CRYPT_FAIL_TESTVECTOR;
512      }
513
514      /* now see if we can encrypt all zero bytes 1000 times, decrypt and come back where we started */
515      for (y = 0; y < 16; y++) tmp[0][y] = 0;
516      for (y = 0; y < 1000; y++) saferp_ecb_encrypt(tmp[0], tmp[0], &skey);
517      for (y = 0; y < 1000; y++) saferp_ecb_decrypt(tmp[0], tmp[0], &skey);
518      for (y = 0; y < 16; y++) if (tmp[0][y] != 0) return CRYPT_FAIL_TESTVECTOR;
519   }
520
521   return CRYPT_OK;
522 #endif
523}
524
525/** Terminate the context
526   @param skey    The scheduled key
527*/
528void saferp_done(symmetric_key *skey)
529{
530}
531
532/**
533  Gets suitable key size
534  @param keysize [in/out] The length of the recommended key (in bytes).  This function will store the suitable size back in this variable.
535  @return CRYPT_OK if the input key size is acceptable.
536*/
537int saferp_keysize(int *keysize)
538{
539   LTC_ARGCHK(keysize != NULL);
540
541   if (*keysize < 16)
542      return CRYPT_INVALID_KEYSIZE;
543   if (*keysize < 24) {
544      *keysize = 16;
545   } else if (*keysize < 32) {
546      *keysize = 24;
547   } else {
548      *keysize = 32;
549   }
550   return CRYPT_OK;
551}
552
553#endif
554
555
556
557/* $Source: /cvs/libtom/libtomcrypt/src/ciphers/safer/saferp.c,v $ */
558/* $Revision: 1.12 $ */
559/* $Date: 2006/11/08 23:01:06 $ */
560