1 /* LibTomCrypt, modular cryptographic library -- Tom St Denis
3 * LibTomCrypt is a library that provides various cryptographic
4 * algorithms in a highly modular and flexible manner.
6 * The library is free for all purposes without any express
12 Multi-2 implementation (not public domain, hence the default disable)
18 static void pi1(ulong32 *p)
23 static void pi2(ulong32 *p, ulong32 *k)
26 t = (p[1] + k[0]) & 0xFFFFFFFFUL;
27 t = (ROL(t, 1) + t - 1) & 0xFFFFFFFFUL;
28 t = (ROL(t, 4) ^ t) & 0xFFFFFFFFUL;
32 static void pi3(ulong32 *p, ulong32 *k)
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);
44 static void pi4(ulong32 *p, ulong32 *k)
47 t = (p[1] + k[3]) & 0xFFFFFFFFUL;
48 t = (ROL(t, 2) + t + 1) & 0xFFFFFFFFUL;
52 static void setup(ulong32 *dk, ulong32 *k, ulong32 *uk)
57 p[0] = dk[0]; p[1] = dk[1];
80 static void encrypt(ulong32 *p, int N, ulong32 *uk)
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;
92 static void decrypt(ulong32 *p, int N, ulong32 *uk)
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;
107 const struct ltc_cipher_descriptor multi2_desc = {
117 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
120 int multi2_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey)
122 ulong32 sk[8], dk[2];
125 LTC_ARGCHK(key != NULL);
126 LTC_ARGCHK(skey != NULL);
128 if (keylen != 40) return CRYPT_INVALID_KEYSIZE;
129 if (num_rounds == 0) num_rounds = 128;
131 skey->multi2.N = num_rounds;
132 for (x = 0; x < 8; x++) {
133 LOAD32H(sk[x], key + x*4);
135 LOAD32H(dk[0], key + 32);
136 LOAD32H(dk[1], key + 36);
137 setup(dk, sk, skey->multi2.uk);
139 zeromem(sk, sizeof(sk));
140 zeromem(dk, sizeof(dk));
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
151 int multi2_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey)
154 LTC_ARGCHK(pt != NULL);
155 LTC_ARGCHK(ct != NULL);
156 LTC_ARGCHK(skey != NULL);
159 encrypt(p, skey->multi2.N, skey->multi2.uk);
161 STORE32H(p[1], ct+4);
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
172 int multi2_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey)
175 LTC_ARGCHK(pt != NULL);
176 LTC_ARGCHK(ct != NULL);
177 LTC_ARGCHK(skey != NULL);
180 decrypt(p, skey->multi2.N, skey->multi2.uk);
182 STORE32H(p[1], pt+4);
187 Performs a self-test of the multi2 block cipher
188 @return CRYPT_OK if functional, CRYPT_NOP if self-test has been disabled
190 int multi2_test(void)
192 static const struct {
193 unsigned char key[40];
194 unsigned char pt[8], ct[8];
199 0x00, 0x00, 0x00, 0x00,
200 0x00, 0x00, 0x00, 0x00,
201 0x00, 0x00, 0x00, 0x00,
202 0x00, 0x00, 0x00, 0x00,
204 0x00, 0x00, 0x00, 0x00,
205 0x00, 0x00, 0x00, 0x00,
206 0x00, 0x00, 0x00, 0x00,
207 0x00, 0x00, 0x00, 0x00,
209 0x01, 0x23, 0x45, 0x67,
210 0x89, 0xAB, 0xCD, 0xEF
213 0x00, 0x00, 0x00, 0x00,
214 0x00, 0x00, 0x00, 0x01,
217 0xf8, 0x94, 0x40, 0x84,
218 0x5e, 0x11, 0xcf, 0x89
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,
233 0xb1, 0x27, 0xb9, 0x06,
234 0xe7, 0x56, 0x22, 0x38,
237 0x1f, 0xb4, 0x60, 0x60,
238 0xd0, 0xb3, 0x4f, 0xa5
241 0xca, 0x84, 0xa9, 0x34,
242 0x75, 0xc8, 0x60, 0xe5
247 unsigned char buf[8];
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) {
255 if ((err = multi2_ecb_encrypt(tests[x].pt, buf, &skey)) != CRYPT_OK) {
259 if (compare_testvector(buf, 8, tests[x].ct, 8, "Multi2 Encrypt", x)) {
260 return CRYPT_FAIL_TESTVECTOR;
263 if ((err = multi2_ecb_decrypt(buf, buf, &skey)) != CRYPT_OK) {
266 if (compare_testvector(buf, 8, tests[x].pt, 8, "Multi2 Decrypt", x)) {
267 return CRYPT_FAIL_TESTVECTOR;
271 for (x = 128; x < 256; ++x) {
274 if ((err = multi2_setup(tests[0].key, 40, x, &skey)) != CRYPT_OK) {
277 if ((err = multi2_ecb_encrypt(tests[0].pt, ct, &skey)) != CRYPT_OK) {
280 if ((err = multi2_ecb_decrypt(ct, buf, &skey)) != CRYPT_OK) {
283 if (compare_testvector(buf, 8, tests[0].pt, 8, "Multi2 Rounds", x)) {
284 return CRYPT_FAIL_TESTVECTOR;
291 /** Terminate the context
292 @param skey The scheduled key
294 void multi2_done(symmetric_key *skey)
296 LTC_UNUSED_PARAM(skey);
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.
304 int multi2_keysize(int *keysize)
306 LTC_ARGCHK(keysize != NULL);
307 if (*keysize >= 40) {
310 return CRYPT_INVALID_KEYSIZE;
317 /* ref: $Format:%D$ */
318 /* git commit: $Format:%H$ */
319 /* commit time: $Format:%ai$ */