Mercurial > dropbear
comparison libtomcrypt/src/ciphers/multi2.c @ 1435:f849a5ca2efc
update to libtomcrypt 1.17 (with Dropbear changes)
author | Matt Johnston <matt@ucc.asn.au> |
---|---|
date | Sat, 24 Jun 2017 17:50:50 +0800 |
parents | |
children | 6dba84798cd5 |
comparison
equal
deleted
inserted
replaced
1434:27b9ddb06b09 | 1435:f849a5ca2efc |
---|---|
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://libtom.org | |
10 */ | |
11 | |
12 /** | |
13 @file multi2.c | |
14 Multi-2 implementation (not public domain, hence the default disable) | |
15 */ | |
16 #include "tomcrypt.h" | |
17 | |
18 #ifdef LTC_MULTI2 | |
19 | |
20 static void pi1(ulong32 *p) | |
21 { | |
22 p[1] ^= p[0]; | |
23 } | |
24 | |
25 static void pi2(ulong32 *p, ulong32 *k) | |
26 { | |
27 ulong32 t; | |
28 t = (p[1] + k[0]) & 0xFFFFFFFFUL; | |
29 t = (ROL(t, 1) + t - 1) & 0xFFFFFFFFUL; | |
30 t = (ROL(t, 4) ^ t) & 0xFFFFFFFFUL; | |
31 p[0] ^= t; | |
32 } | |
33 | |
34 static void pi3(ulong32 *p, ulong32 *k) | |
35 { | |
36 ulong32 t; | |
37 t = p[0] + k[1]; | |
38 t = (ROL(t, 2) + t + 1) & 0xFFFFFFFFUL; | |
39 t = (ROL(t, 8) ^ t) & 0xFFFFFFFFUL; | |
40 t = (t + k[2]) & 0xFFFFFFFFUL; | |
41 t = (ROL(t, 1) - t) & 0xFFFFFFFFUL; | |
42 t = ROL(t, 16) ^ (p[0] | t); | |
43 p[1] ^= t; | |
44 } | |
45 | |
46 static void pi4(ulong32 *p, ulong32 *k) | |
47 { | |
48 ulong32 t; | |
49 t = (p[1] + k[3]) & 0xFFFFFFFFUL; | |
50 t = (ROL(t, 2) + t + 1) & 0xFFFFFFFFUL; | |
51 p[0] ^= t; | |
52 } | |
53 | |
54 static void setup(ulong32 *dk, ulong32 *k, ulong32 *uk) | |
55 { | |
56 int n, t; | |
57 ulong32 p[2]; | |
58 | |
59 p[0] = dk[0]; p[1] = dk[1]; | |
60 | |
61 t = 4; | |
62 n = 0; | |
63 pi1(p); | |
64 pi2(p, k); | |
65 uk[n++] = p[0]; | |
66 pi3(p, k); | |
67 uk[n++] = p[1]; | |
68 pi4(p, k); | |
69 uk[n++] = p[0]; | |
70 pi1(p); | |
71 uk[n++] = p[1]; | |
72 pi2(p, k+t); | |
73 uk[n++] = p[0]; | |
74 pi3(p, k+t); | |
75 uk[n++] = p[1]; | |
76 pi4(p, k+t); | |
77 uk[n++] = p[0]; | |
78 pi1(p); | |
79 uk[n++] = p[1]; | |
80 } | |
81 | |
82 static void encrypt(ulong32 *p, int N, ulong32 *uk) | |
83 { | |
84 int n, t; | |
85 for (t = n = 0; ; ) { | |
86 pi1(p); if (++n == N) break; | |
87 pi2(p, uk+t); if (++n == N) break; | |
88 pi3(p, uk+t); if (++n == N) break; | |
89 pi4(p, uk+t); if (++n == N) break; | |
90 t ^= 4; | |
91 } | |
92 } | |
93 | |
94 static void decrypt(ulong32 *p, int N, ulong32 *uk) | |
95 { | |
96 int n, t; | |
97 for (t = 4*((N&1)^1), n = N; ; ) { | |
98 switch (n >= 4 ? 4 : 0) { | |
99 case 4: pi4(p, uk+t); --n; | |
100 case 3: pi3(p, uk+t); --n; | |
101 case 2: pi2(p, uk+t); --n; | |
102 case 1: pi1(p); --n; break; | |
103 case 0: return; | |
104 } | |
105 t ^= 4; | |
106 } | |
107 } | |
108 | |
109 const struct ltc_cipher_descriptor multi2_desc = { | |
110 "multi2", | |
111 22, | |
112 40, 40, 8, 128, | |
113 &multi2_setup, | |
114 &multi2_ecb_encrypt, | |
115 &multi2_ecb_decrypt, | |
116 &multi2_test, | |
117 &multi2_done, | |
118 &multi2_keysize, | |
119 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL | |
120 }; | |
121 | |
122 int multi2_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey) | |
123 { | |
124 ulong32 sk[8], dk[2]; | |
125 int x; | |
126 | |
127 LTC_ARGCHK(key != NULL); | |
128 LTC_ARGCHK(skey != NULL); | |
129 | |
130 if (keylen != 40) return CRYPT_INVALID_KEYSIZE; | |
131 if (num_rounds == 0) num_rounds = 128; | |
132 | |
133 skey->multi2.N = num_rounds; | |
134 for (x = 0; x < 8; x++) { | |
135 LOAD32H(sk[x], key + x*4); | |
136 } | |
137 LOAD32H(dk[0], key + 32); | |
138 LOAD32H(dk[1], key + 36); | |
139 setup(dk, sk, skey->multi2.uk); | |
140 | |
141 zeromem(sk, sizeof(sk)); | |
142 zeromem(dk, sizeof(dk)); | |
143 return CRYPT_OK; | |
144 } | |
145 | |
146 /** | |
147 Encrypts a block of text with multi2 | |
148 @param pt The input plaintext (8 bytes) | |
149 @param ct The output ciphertext (8 bytes) | |
150 @param skey The key as scheduled | |
151 @return CRYPT_OK if successful | |
152 */ | |
153 int multi2_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey) | |
154 { | |
155 ulong32 p[2]; | |
156 LTC_ARGCHK(pt != NULL); | |
157 LTC_ARGCHK(ct != NULL); | |
158 LTC_ARGCHK(skey != NULL); | |
159 LOAD32H(p[0], pt); | |
160 LOAD32H(p[1], pt+4); | |
161 encrypt(p, skey->multi2.N, skey->multi2.uk); | |
162 STORE32H(p[0], ct); | |
163 STORE32H(p[1], ct+4); | |
164 return CRYPT_OK; | |
165 } | |
166 | |
167 /** | |
168 Decrypts a block of text with multi2 | |
169 @param ct The input ciphertext (8 bytes) | |
170 @param pt The output plaintext (8 bytes) | |
171 @param skey The key as scheduled | |
172 @return CRYPT_OK if successful | |
173 */ | |
174 int multi2_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey) | |
175 { | |
176 ulong32 p[2]; | |
177 LTC_ARGCHK(pt != NULL); | |
178 LTC_ARGCHK(ct != NULL); | |
179 LTC_ARGCHK(skey != NULL); | |
180 LOAD32H(p[0], ct); | |
181 LOAD32H(p[1], ct+4); | |
182 decrypt(p, skey->multi2.N, skey->multi2.uk); | |
183 STORE32H(p[0], pt); | |
184 STORE32H(p[1], pt+4); | |
185 return CRYPT_OK; | |
186 } | |
187 | |
188 /** | |
189 Performs a self-test of the multi2 block cipher | |
190 @return CRYPT_OK if functional, CRYPT_NOP if self-test has been disabled | |
191 */ | |
192 int multi2_test(void) | |
193 { | |
194 static const struct { | |
195 unsigned char key[40]; | |
196 unsigned char pt[8], ct[8]; | |
197 int rounds; | |
198 } tests[] = { | |
199 { | |
200 { | |
201 0x00, 0x00, 0x00, 0x00, | |
202 0x00, 0x00, 0x00, 0x00, | |
203 0x00, 0x00, 0x00, 0x00, | |
204 0x00, 0x00, 0x00, 0x00, | |
205 | |
206 0x00, 0x00, 0x00, 0x00, | |
207 0x00, 0x00, 0x00, 0x00, | |
208 0x00, 0x00, 0x00, 0x00, | |
209 0x00, 0x00, 0x00, 0x00, | |
210 | |
211 0x01, 0x23, 0x45, 0x67, | |
212 0x89, 0xAB, 0xCD, 0xEF | |
213 }, | |
214 { | |
215 0x00, 0x00, 0x00, 0x00, | |
216 0x00, 0x00, 0x00, 0x01, | |
217 }, | |
218 { | |
219 0xf8, 0x94, 0x40, 0x84, | |
220 0x5e, 0x11, 0xcf, 0x89 | |
221 }, | |
222 128, | |
223 }, | |
224 { | |
225 { | |
226 0x35, 0x91, 0x9d, 0x96, | |
227 0x07, 0x02, 0xe2, 0xce, | |
228 0x8d, 0x0b, 0x58, 0x3c, | |
229 0xc9, 0xc8, 0x9d, 0x59, | |
230 0xa2, 0xae, 0x96, 0x4e, | |
231 0x87, 0x82, 0x45, 0xed, | |
232 0x3f, 0x2e, 0x62, 0xd6, | |
233 0x36, 0x35, 0xd0, 0x67, | |
234 | |
235 0xb1, 0x27, 0xb9, 0x06, | |
236 0xe7, 0x56, 0x22, 0x38, | |
237 }, | |
238 { | |
239 0x1f, 0xb4, 0x60, 0x60, | |
240 0xd0, 0xb3, 0x4f, 0xa5 | |
241 }, | |
242 { | |
243 0xca, 0x84, 0xa9, 0x34, | |
244 0x75, 0xc8, 0x60, 0xe5 | |
245 }, | |
246 216, | |
247 } | |
248 }; | |
249 unsigned char buf[8]; | |
250 symmetric_key skey; | |
251 int err, x; | |
252 | |
253 for (x = 1; x < (int)(sizeof(tests)/sizeof(tests[0])); x++) { | |
254 if ((err = multi2_setup(tests[x].key, 40, tests[x].rounds, &skey)) != CRYPT_OK) { | |
255 return err; | |
256 } | |
257 if ((err = multi2_ecb_encrypt(tests[x].pt, buf, &skey)) != CRYPT_OK) { | |
258 return err; | |
259 } | |
260 | |
261 if (XMEMCMP(buf, tests[x].ct, 8)) { | |
262 return CRYPT_FAIL_TESTVECTOR; | |
263 } | |
264 | |
265 if ((err = multi2_ecb_decrypt(buf, buf, &skey)) != CRYPT_OK) { | |
266 return err; | |
267 } | |
268 if (XMEMCMP(buf, tests[x].pt, 8)) { | |
269 return CRYPT_FAIL_TESTVECTOR; | |
270 } | |
271 } | |
272 | |
273 return CRYPT_OK; | |
274 } | |
275 | |
276 /** Terminate the context | |
277 @param skey The scheduled key | |
278 */ | |
279 void multi2_done(symmetric_key *skey) | |
280 { | |
281 } | |
282 | |
283 /** | |
284 Gets suitable key size | |
285 @param keysize [in/out] The length of the recommended key (in bytes). This function will store the suitable size back in this variable. | |
286 @return CRYPT_OK if the input key size is acceptable. | |
287 */ | |
288 int multi2_keysize(int *keysize) | |
289 { | |
290 LTC_ARGCHK(keysize != NULL); | |
291 if (*keysize >= 40) { | |
292 *keysize = 40; | |
293 } else { | |
294 return CRYPT_INVALID_KEYSIZE; | |
295 } | |
296 return CRYPT_OK; | |
297 } | |
298 | |
299 #endif | |
300 | |
301 /* $Source$ */ | |
302 /* $Revision$ */ | |
303 /* $Date$ */ |