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$ */