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