Mercurial > dropbear
comparison libtomcrypt/src/ciphers/safer/saferp.c @ 285:1b9e69c058d2
propagate from branch 'au.asn.ucc.matt.ltc.dropbear' (head 20dccfc09627970a312d77fb41dc2970b62689c3)
to branch 'au.asn.ucc.matt.dropbear' (head fdf4a7a3b97ae5046139915de7e40399cceb2c01)
author | Matt Johnston <matt@ucc.asn.au> |
---|---|
date | Wed, 08 Mar 2006 13:23:58 +0000 |
parents | |
children | 0cbe8f6dbf9e |
comparison
equal
deleted
inserted
replaced
281:997e6f7dc01e | 285:1b9e69c058d2 |
---|---|
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, [email protected], http://libtomcrypt.org | |
10 */ | |
11 | |
12 /** | |
13 @file saferp.c | |
14 SAFER+ Implementation by Tom St Denis | |
15 */ | |
16 #include "tomcrypt.h" | |
17 | |
18 #ifdef SAFERP | |
19 | |
20 const 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 | |
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 | |
45 extern 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 | |
139 static void _round(unsigned char *b, int i, symmetric_key *skey) | |
140 { | |
141 ROUND(b, i); | |
142 } | |
143 | |
144 static void _iround(unsigned char *b, int i, symmetric_key *skey) | |
145 { | |
146 iROUND(b, i); | |
147 } | |
148 | |
149 static void _lt(unsigned char *b, unsigned char *b2) | |
150 { | |
151 LT(b, b2); | |
152 } | |
153 | |
154 static 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 */ | |
174 static 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 */ | |
216 int 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 */ | |
333 void saferp_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey) | |
334 { | |
335 unsigned char b[16]; | |
336 int x; | |
337 | |
338 LTC_ARGCHK(pt != NULL); | |
339 LTC_ARGCHK(ct != NULL); | |
340 LTC_ARGCHK(skey != NULL); | |
341 | |
342 /* do eight rounds */ | |
343 for (x = 0; x < 16; x++) { | |
344 b[x] = pt[x]; | |
345 } | |
346 ROUND(b, 0); LT(b, ct); | |
347 ROUND(ct, 2); LT(ct, b); | |
348 ROUND(b, 4); LT(b, ct); | |
349 ROUND(ct, 6); LT(ct, b); | |
350 ROUND(b, 8); LT(b, ct); | |
351 ROUND(ct, 10); LT(ct, b); | |
352 ROUND(b, 12); LT(b, ct); | |
353 ROUND(ct, 14); LT(ct, b); | |
354 /* 192-bit key? */ | |
355 if (skey->saferp.rounds > 8) { | |
356 ROUND(b, 16); LT(b, ct); | |
357 ROUND(ct, 18); LT(ct, b); | |
358 ROUND(b, 20); LT(b, ct); | |
359 ROUND(ct, 22); LT(ct, b); | |
360 } | |
361 /* 256-bit key? */ | |
362 if (skey->saferp.rounds > 12) { | |
363 ROUND(b, 24); LT(b, ct); | |
364 ROUND(ct, 26); LT(ct, b); | |
365 ROUND(b, 28); LT(b, ct); | |
366 ROUND(ct, 30); LT(ct, b); | |
367 } | |
368 ct[0] = b[0] ^ skey->saferp.K[skey->saferp.rounds*2][0]; | |
369 ct[1] = (b[1] + skey->saferp.K[skey->saferp.rounds*2][1]) & 255; | |
370 ct[2] = (b[2] + skey->saferp.K[skey->saferp.rounds*2][2]) & 255; | |
371 ct[3] = b[3] ^ skey->saferp.K[skey->saferp.rounds*2][3]; | |
372 ct[4] = b[4] ^ skey->saferp.K[skey->saferp.rounds*2][4]; | |
373 ct[5] = (b[5] + skey->saferp.K[skey->saferp.rounds*2][5]) & 255; | |
374 ct[6] = (b[6] + skey->saferp.K[skey->saferp.rounds*2][6]) & 255; | |
375 ct[7] = b[7] ^ skey->saferp.K[skey->saferp.rounds*2][7]; | |
376 ct[8] = b[8] ^ skey->saferp.K[skey->saferp.rounds*2][8]; | |
377 ct[9] = (b[9] + skey->saferp.K[skey->saferp.rounds*2][9]) & 255; | |
378 ct[10] = (b[10] + skey->saferp.K[skey->saferp.rounds*2][10]) & 255; | |
379 ct[11] = b[11] ^ skey->saferp.K[skey->saferp.rounds*2][11]; | |
380 ct[12] = b[12] ^ skey->saferp.K[skey->saferp.rounds*2][12]; | |
381 ct[13] = (b[13] + skey->saferp.K[skey->saferp.rounds*2][13]) & 255; | |
382 ct[14] = (b[14] + skey->saferp.K[skey->saferp.rounds*2][14]) & 255; | |
383 ct[15] = b[15] ^ skey->saferp.K[skey->saferp.rounds*2][15]; | |
384 #ifdef LTC_CLEAN_STACK | |
385 zeromem(b, sizeof(b)); | |
386 #endif | |
387 } | |
388 | |
389 /** | |
390 Decrypts a block of text with SAFER+ | |
391 @param ct The input ciphertext (16 bytes) | |
392 @param pt The output plaintext (16 bytes) | |
393 @param skey The key as scheduled | |
394 */ | |
395 void saferp_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey) | |
396 { | |
397 unsigned char b[16]; | |
398 int x; | |
399 | |
400 LTC_ARGCHK(pt != NULL); | |
401 LTC_ARGCHK(ct != NULL); | |
402 LTC_ARGCHK(skey != NULL); | |
403 | |
404 /* do eight rounds */ | |
405 b[0] = ct[0] ^ skey->saferp.K[skey->saferp.rounds*2][0]; | |
406 b[1] = (ct[1] - skey->saferp.K[skey->saferp.rounds*2][1]) & 255; | |
407 b[2] = (ct[2] - skey->saferp.K[skey->saferp.rounds*2][2]) & 255; | |
408 b[3] = ct[3] ^ skey->saferp.K[skey->saferp.rounds*2][3]; | |
409 b[4] = ct[4] ^ skey->saferp.K[skey->saferp.rounds*2][4]; | |
410 b[5] = (ct[5] - skey->saferp.K[skey->saferp.rounds*2][5]) & 255; | |
411 b[6] = (ct[6] - skey->saferp.K[skey->saferp.rounds*2][6]) & 255; | |
412 b[7] = ct[7] ^ skey->saferp.K[skey->saferp.rounds*2][7]; | |
413 b[8] = ct[8] ^ skey->saferp.K[skey->saferp.rounds*2][8]; | |
414 b[9] = (ct[9] - skey->saferp.K[skey->saferp.rounds*2][9]) & 255; | |
415 b[10] = (ct[10] - skey->saferp.K[skey->saferp.rounds*2][10]) & 255; | |
416 b[11] = ct[11] ^ skey->saferp.K[skey->saferp.rounds*2][11]; | |
417 b[12] = ct[12] ^ skey->saferp.K[skey->saferp.rounds*2][12]; | |
418 b[13] = (ct[13] - skey->saferp.K[skey->saferp.rounds*2][13]) & 255; | |
419 b[14] = (ct[14] - skey->saferp.K[skey->saferp.rounds*2][14]) & 255; | |
420 b[15] = ct[15] ^ skey->saferp.K[skey->saferp.rounds*2][15]; | |
421 /* 256-bit key? */ | |
422 if (skey->saferp.rounds > 12) { | |
423 iLT(b, pt); iROUND(pt, 30); | |
424 iLT(pt, b); iROUND(b, 28); | |
425 iLT(b, pt); iROUND(pt, 26); | |
426 iLT(pt, b); iROUND(b, 24); | |
427 } | |
428 /* 192-bit key? */ | |
429 if (skey->saferp.rounds > 8) { | |
430 iLT(b, pt); iROUND(pt, 22); | |
431 iLT(pt, b); iROUND(b, 20); | |
432 iLT(b, pt); iROUND(pt, 18); | |
433 iLT(pt, b); iROUND(b, 16); | |
434 } | |
435 iLT(b, pt); iROUND(pt, 14); | |
436 iLT(pt, b); iROUND(b, 12); | |
437 iLT(b, pt); iROUND(pt,10); | |
438 iLT(pt, b); iROUND(b, 8); | |
439 iLT(b, pt); iROUND(pt,6); | |
440 iLT(pt, b); iROUND(b, 4); | |
441 iLT(b, pt); iROUND(pt,2); | |
442 iLT(pt, b); iROUND(b, 0); | |
443 for (x = 0; x < 16; x++) { | |
444 pt[x] = b[x]; | |
445 } | |
446 #ifdef LTC_CLEAN_STACK | |
447 zeromem(b, sizeof(b)); | |
448 #endif | |
449 } | |
450 | |
451 /** | |
452 Performs a self-test of the SAFER+ block cipher | |
453 @return CRYPT_OK if functional, CRYPT_NOP if self-test has been disabled | |
454 */ | |
455 int saferp_test(void) | |
456 { | |
457 #ifndef LTC_TEST | |
458 return CRYPT_NOP; | |
459 #else | |
460 static const struct { | |
461 int keylen; | |
462 unsigned char key[32], pt[16], ct[16]; | |
463 } tests[] = { | |
464 { | |
465 16, | |
466 { 41, 35, 190, 132, 225, 108, 214, 174, | |
467 82, 144, 73, 241, 241, 187, 233, 235 }, | |
468 { 179, 166, 219, 60, 135, 12, 62, 153, | |
469 36, 94, 13, 28, 6, 183, 71, 222 }, | |
470 { 224, 31, 182, 10, 12, 255, 84, 70, | |
471 127, 13, 89, 249, 9, 57, 165, 220 } | |
472 }, { | |
473 24, | |
474 { 72, 211, 143, 117, 230, 217, 29, 42, | |
475 229, 192, 247, 43, 120, 129, 135, 68, | |
476 14, 95, 80, 0, 212, 97, 141, 190 }, | |
477 { 123, 5, 21, 7, 59, 51, 130, 31, | |
478 24, 112, 146, 218, 100, 84, 206, 177 }, | |
479 { 92, 136, 4, 63, 57, 95, 100, 0, | |
480 150, 130, 130, 16, 193, 111, 219, 133 } | |
481 }, { | |
482 32, | |
483 { 243, 168, 141, 254, 190, 242, 235, 113, | |
484 255, 160, 208, 59, 117, 6, 140, 126, | |
485 135, 120, 115, 77, 208, 190, 130, 190, | |
486 219, 194, 70, 65, 43, 140, 250, 48 }, | |
487 { 127, 112, 240, 167, 84, 134, 50, 149, | |
488 170, 91, 104, 19, 11, 230, 252, 245 }, | |
489 { 88, 11, 25, 36, 172, 229, 202, 213, | |
490 170, 65, 105, 153, 220, 104, 153, 138 } | |
491 } | |
492 }; | |
493 | |
494 unsigned char tmp[2][16]; | |
495 symmetric_key skey; | |
496 int err, i, y; | |
497 | |
498 for (i = 0; i < (int)(sizeof(tests) / sizeof(tests[0])); i++) { | |
499 if ((err = saferp_setup(tests[i].key, tests[i].keylen, 0, &skey)) != CRYPT_OK) { | |
500 return err; | |
501 } | |
502 saferp_ecb_encrypt(tests[i].pt, tmp[0], &skey); | |
503 saferp_ecb_decrypt(tmp[0], tmp[1], &skey); | |
504 | |
505 /* compare */ | |
506 if (memcmp(tmp[0], tests[i].ct, 16) || memcmp(tmp[1], tests[i].pt, 16)) { | |
507 return CRYPT_FAIL_TESTVECTOR; | |
508 } | |
509 | |
510 /* now see if we can encrypt all zero bytes 1000 times, decrypt and come back where we started */ | |
511 for (y = 0; y < 16; y++) tmp[0][y] = 0; | |
512 for (y = 0; y < 1000; y++) saferp_ecb_encrypt(tmp[0], tmp[0], &skey); | |
513 for (y = 0; y < 1000; y++) saferp_ecb_decrypt(tmp[0], tmp[0], &skey); | |
514 for (y = 0; y < 16; y++) if (tmp[0][y] != 0) return CRYPT_FAIL_TESTVECTOR; | |
515 } | |
516 | |
517 return CRYPT_OK; | |
518 #endif | |
519 } | |
520 | |
521 /** Terminate the context | |
522 @param skey The scheduled key | |
523 */ | |
524 void saferp_done(symmetric_key *skey) | |
525 { | |
526 } | |
527 | |
528 /** | |
529 Gets suitable key size | |
530 @param keysize [in/out] The length of the recommended key (in bytes). This function will store the suitable size back in this variable. | |
531 @return CRYPT_OK if the input key size is acceptable. | |
532 */ | |
533 int saferp_keysize(int *keysize) | |
534 { | |
535 LTC_ARGCHK(keysize != NULL); | |
536 | |
537 if (*keysize < 16) | |
538 return CRYPT_INVALID_KEYSIZE; | |
539 if (*keysize < 24) { | |
540 *keysize = 16; | |
541 } else if (*keysize < 32) { | |
542 *keysize = 24; | |
543 } else { | |
544 *keysize = 32; | |
545 } | |
546 return CRYPT_OK; | |
547 } | |
548 | |
549 #endif | |
550 | |
551 | |
552 | |
553 /* $Source: /cvs/libtom/libtomcrypt/src/ciphers/safer/saferp.c,v $ */ | |
554 /* $Revision: 1.7 $ */ | |
555 /* $Date: 2005/05/05 14:35:58 $ */ |