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