xref: /openbsd/lib/libcrypto/idea/idea.c (revision cc6c685f)
1 /* $OpenBSD: idea.c,v 1.1 2024/03/29 05:23:50 jsing Exp $ */
2 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
3  * All rights reserved.
4  *
5  * This package is an SSL implementation written
6  * by Eric Young (eay@cryptsoft.com).
7  * The implementation was written so as to conform with Netscapes SSL.
8  *
9  * This library is free for commercial and non-commercial use as long as
10  * the following conditions are aheared to.  The following conditions
11  * apply to all code found in this distribution, be it the RC4, RSA,
12  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
13  * included with this distribution is covered by the same copyright terms
14  * except that the holder is Tim Hudson (tjh@cryptsoft.com).
15  *
16  * Copyright remains Eric Young's, and as such any Copyright notices in
17  * the code are not to be removed.
18  * If this package is used in a product, Eric Young should be given attribution
19  * as the author of the parts of the library used.
20  * This can be in the form of a textual message at program startup or
21  * in documentation (online or textual) provided with the package.
22  *
23  * Redistribution and use in source and binary forms, with or without
24  * modification, are permitted provided that the following conditions
25  * are met:
26  * 1. Redistributions of source code must retain the copyright
27  *    notice, this list of conditions and the following disclaimer.
28  * 2. Redistributions in binary form must reproduce the above copyright
29  *    notice, this list of conditions and the following disclaimer in the
30  *    documentation and/or other materials provided with the distribution.
31  * 3. All advertising materials mentioning features or use of this software
32  *    must display the following acknowledgement:
33  *    "This product includes cryptographic software written by
34  *     Eric Young (eay@cryptsoft.com)"
35  *    The word 'cryptographic' can be left out if the rouines from the library
36  *    being used are not cryptographic related :-).
37  * 4. If you include any Windows specific code (or a derivative thereof) from
38  *    the apps directory (application code) you must include an acknowledgement:
39  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
40  *
41  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
42  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
44  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
45  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
46  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
47  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
49  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
50  * OUT OF THE USE OF THIS  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
51  * SUCH DAMAGE.
52  *
53  * The licence and distribution terms for any publically available version or
54  * derivative of this code cannot be changed.  i.e. this code cannot simply be
55  * copied and put under another distribution licence
56  * [including the GNU Public Licence.]
57  */
58 
59 #include <openssl/idea.h>
60 #include "idea_local.h"
61 
62 void
idea_cbc_encrypt(const unsigned char * in,unsigned char * out,long length,IDEA_KEY_SCHEDULE * ks,unsigned char * iv,int encrypt)63 idea_cbc_encrypt(const unsigned char *in, unsigned char *out, long length,
64     IDEA_KEY_SCHEDULE *ks, unsigned char *iv, int encrypt)
65 {
66 	unsigned long tin0, tin1;
67 	unsigned long tout0, tout1, xor0, xor1;
68 	long l = length;
69 	unsigned long tin[2];
70 
71 	if (encrypt) {
72 		n2l(iv, tout0);
73 		n2l(iv, tout1);
74 		iv -= 8;
75 		for (l -= 8; l >= 0; l -= 8)
76 		{
77 			n2l(in, tin0);
78 			n2l(in, tin1);
79 			tin0 ^= tout0;
80 			tin1 ^= tout1;
81 			tin[0] = tin0;
82 			tin[1] = tin1;
83 			idea_encrypt(tin, ks);
84 			tout0 = tin[0];
85 			l2n(tout0, out);
86 			tout1 = tin[1];
87 			l2n(tout1, out);
88 		}
89 		if (l != -8) {
90 			n2ln(in, tin0, tin1, l + 8);
91 			tin0 ^= tout0;
92 			tin1 ^= tout1;
93 			tin[0] = tin0;
94 			tin[1] = tin1;
95 			idea_encrypt(tin, ks);
96 			tout0 = tin[0];
97 			l2n(tout0, out);
98 			tout1 = tin[1];
99 			l2n(tout1, out);
100 		}
101 		l2n(tout0, iv);
102 		l2n(tout1, iv);
103 	} else {
104 		n2l(iv, xor0);
105 		n2l(iv, xor1);
106 		iv -= 8;
107 		for (l -= 8; l >= 0; l -= 8)
108 		{
109 			n2l(in, tin0);
110 			tin[0] = tin0;
111 			n2l(in, tin1);
112 			tin[1] = tin1;
113 			idea_encrypt(tin, ks);
114 			tout0 = tin[0] ^ xor0;
115 			tout1 = tin[1] ^ xor1;
116 			l2n(tout0, out);
117 			l2n(tout1, out);
118 			xor0 = tin0;
119 			xor1 = tin1;
120 		}
121 		if (l != -8) {
122 			n2l(in, tin0);
123 			tin[0] = tin0;
124 			n2l(in, tin1);
125 			tin[1] = tin1;
126 			idea_encrypt(tin, ks);
127 			tout0 = tin[0] ^ xor0;
128 			tout1 = tin[1] ^ xor1;
129 			l2nn(tout0, tout1, out, l + 8);
130 			xor0 = tin0;
131 			xor1 = tin1;
132 		}
133 		l2n(xor0, iv);
134 		l2n(xor1, iv);
135 	}
136 	tin0 = tin1 = tout0 = tout1 = xor0 = xor1 = 0;
137 	tin[0] = tin[1] = 0;
138 }
139 LCRYPTO_ALIAS(idea_cbc_encrypt);
140 
141 void
idea_encrypt(unsigned long * d,IDEA_KEY_SCHEDULE * key)142 idea_encrypt(unsigned long *d, IDEA_KEY_SCHEDULE *key)
143 {
144 	IDEA_INT *p;
145 	unsigned long x1, x2, x3, x4, t0, t1, ul;
146 
147 	x2 = d[0];
148 	x1 = (x2 >> 16);
149 	x4 = d[1];
150 	x3 = (x4 >> 16);
151 
152 	p = &(key->data[0][0]);
153 
154 	E_IDEA(0);
155 	E_IDEA(1);
156 	E_IDEA(2);
157 	E_IDEA(3);
158 	E_IDEA(4);
159 	E_IDEA(5);
160 	E_IDEA(6);
161 	E_IDEA(7);
162 
163 	x1 &= 0xffff;
164 	idea_mul(x1, x1, *p, ul);
165 	p++;
166 
167 	t0 = x3 + *(p++);
168 	t1 = x2 + *(p++);
169 
170 	x4 &= 0xffff;
171 	idea_mul(x4, x4, *p, ul);
172 
173 	d[0] = (t0 & 0xffff)|((x1 & 0xffff) << 16);
174 	d[1] = (x4 & 0xffff)|((t1 & 0xffff) << 16);
175 }
176 LCRYPTO_ALIAS(idea_encrypt);
177 
178 /* The input and output encrypted as though 64bit cfb mode is being
179  * used.  The extra state information to record how much of the
180  * 64bit block we have used is contained in *num;
181  */
182 
183 void
idea_cfb64_encrypt(const unsigned char * in,unsigned char * out,long length,IDEA_KEY_SCHEDULE * schedule,unsigned char * ivec,int * num,int encrypt)184 idea_cfb64_encrypt(const unsigned char *in, unsigned char *out,
185     long length, IDEA_KEY_SCHEDULE *schedule,
186     unsigned char *ivec, int *num, int encrypt)
187 {
188 	unsigned long v0, v1, t;
189 	int n = *num;
190 	long l = length;
191 	unsigned long ti[2];
192 	unsigned char *iv, c, cc;
193 
194 	iv = (unsigned char *)ivec;
195 	if (encrypt) {
196 		while (l--) {
197 			if (n == 0) {
198 				n2l(iv, v0);
199 				ti[0] = v0;
200 				n2l(iv, v1);
201 				ti[1] = v1;
202 				idea_encrypt((unsigned long *)ti, schedule);
203 				iv = (unsigned char *)ivec;
204 				t = ti[0];
205 				l2n(t, iv);
206 				t = ti[1];
207 				l2n(t, iv);
208 				iv = (unsigned char *)ivec;
209 			}
210 			c = *(in++) ^ iv[n];
211 			*(out++) = c;
212 			iv[n] = c;
213 			n = (n + 1) & 0x07;
214 		}
215 	} else {
216 		while (l--) {
217 			if (n == 0) {
218 				n2l(iv, v0);
219 				ti[0] = v0;
220 				n2l(iv, v1);
221 				ti[1] = v1;
222 				idea_encrypt((unsigned long *)ti, schedule);
223 				iv = (unsigned char *)ivec;
224 				t = ti[0];
225 				l2n(t, iv);
226 				t = ti[1];
227 				l2n(t, iv);
228 				iv = (unsigned char *)ivec;
229 			}
230 			cc = *(in++);
231 			c = iv[n];
232 			iv[n] = cc;
233 			*(out++) = c ^ cc;
234 			n = (n + 1) & 0x07;
235 		}
236 	}
237 	v0 = v1 = ti[0] = ti[1] = t = c = cc = 0;
238 	*num = n;
239 }
240 LCRYPTO_ALIAS(idea_cfb64_encrypt);
241 
242 void
idea_ecb_encrypt(const unsigned char * in,unsigned char * out,IDEA_KEY_SCHEDULE * ks)243 idea_ecb_encrypt(const unsigned char *in, unsigned char *out,
244     IDEA_KEY_SCHEDULE *ks)
245 {
246 	unsigned long l0, l1, d[2];
247 
248 	n2l(in, l0);
249 	d[0] = l0;
250 	n2l(in, l1);
251 	d[1] = l1;
252 	idea_encrypt(d, ks);
253 	l0 = d[0];
254 	l2n(l0, out);
255 	l1 = d[1];
256 	l2n(l1, out);
257 	l0 = l1 = d[0] = d[1] = 0;
258 }
259 LCRYPTO_ALIAS(idea_ecb_encrypt);
260 
261 /*
262  * The input and output encrypted as though 64bit ofb mode is being
263  * used.  The extra state information to record how much of the
264  * 64bit block we have used is contained in *num;
265  */
266 void
idea_ofb64_encrypt(const unsigned char * in,unsigned char * out,long length,IDEA_KEY_SCHEDULE * schedule,unsigned char * ivec,int * num)267 idea_ofb64_encrypt(const unsigned char *in, unsigned char *out,
268     long length, IDEA_KEY_SCHEDULE *schedule,
269     unsigned char *ivec, int *num)
270 {
271 	unsigned long v0, v1, t;
272 	int n = *num;
273 	long l = length;
274 	unsigned char d[8];
275 	char *dp;
276 	unsigned long ti[2];
277 	unsigned char *iv;
278 	int save = 0;
279 
280 	iv = (unsigned char *)ivec;
281 	n2l(iv, v0);
282 	n2l(iv, v1);
283 	ti[0] = v0;
284 	ti[1] = v1;
285 	dp = (char *)d;
286 	l2n(v0, dp);
287 	l2n(v1, dp);
288 	while (l--) {
289 		if (n == 0) {
290 			idea_encrypt((unsigned long *)ti, schedule);
291 			dp = (char *)d;
292 			t = ti[0];
293 			l2n(t, dp);
294 			t = ti[1];
295 			l2n(t, dp);
296 			save++;
297 		}
298 		*(out++) = *(in++) ^ d[n];
299 		n = (n + 1) & 0x07;
300 	}
301 	if (save) {
302 		v0 = ti[0];
303 		v1 = ti[1];
304 		iv = (unsigned char *)ivec;
305 		l2n(v0, iv);
306 		l2n(v1, iv);
307 	}
308 	t = v0 = v1 = ti[0] = ti[1] = 0;
309 	*num = n;
310 }
311 LCRYPTO_ALIAS(idea_ofb64_encrypt);
312 
313 /* taken directly from the 'paper' I'll have a look at it later */
314 static IDEA_INT
inverse(unsigned int xin)315 inverse(unsigned int xin)
316 {
317 	long n1, n2, q, r, b1, b2, t;
318 
319 	if (xin == 0)
320 		b2 = 0;
321 	else {
322 		n1 = 0x10001;
323 		n2 = xin;
324 		b2 = 1;
325 		b1 = 0;
326 
327 		do {
328 			r = (n1 % n2);
329 			q = (n1 - r)/n2;
330 			if (r == 0) {
331 				if (b2 < 0)
332 					b2 = 0x10001 + b2;
333 			} else {
334 				n1 = n2;
335 				n2 = r;
336 				t = b2;
337 				b2 = b1 - q*b2;
338 				b1 = t;
339 			}
340 		} while (r != 0);
341 	}
342 	return ((IDEA_INT)b2);
343 }
344 
345 void
idea_set_encrypt_key(const unsigned char * key,IDEA_KEY_SCHEDULE * ks)346 idea_set_encrypt_key(const unsigned char *key, IDEA_KEY_SCHEDULE *ks)
347 {
348 	int i;
349 	IDEA_INT *kt, *kf, r0, r1, r2;
350 
351 	kt = &(ks->data[0][0]);
352 	n2s(key, kt[0]);
353 	n2s(key, kt[1]);
354 	n2s(key, kt[2]);
355 	n2s(key, kt[3]);
356 	n2s(key, kt[4]);
357 	n2s(key, kt[5]);
358 	n2s(key, kt[6]);
359 	n2s(key, kt[7]);
360 
361 	kf = kt;
362 	kt += 8;
363 	for (i = 0; i < 6; i++)
364 	{
365 		r2 = kf[1];
366 		r1 = kf[2];
367 		*(kt++) = ((r2 << 9) | (r1 >> 7)) & 0xffff;
368 		r0 = kf[3];
369 		*(kt++) = ((r1 << 9) | (r0 >> 7)) & 0xffff;
370 		r1 = kf[4];
371 		*(kt++) = ((r0 << 9) | (r1 >> 7)) & 0xffff;
372 		r0 = kf[5];
373 		*(kt++) = ((r1 << 9) | (r0 >> 7)) & 0xffff;
374 		r1 = kf[6];
375 		*(kt++) = ((r0 << 9) | (r1 >> 7)) & 0xffff;
376 		r0 = kf[7];
377 		*(kt++) = ((r1 << 9) | (r0 >> 7)) & 0xffff;
378 		r1 = kf[0];
379 		if (i >= 5)
380 			break;
381 		*(kt++) = ((r0 << 9) | (r1 >> 7)) & 0xffff;
382 		*(kt++) = ((r1 << 9) | (r2 >> 7)) & 0xffff;
383 		kf += 8;
384 	}
385 }
386 LCRYPTO_ALIAS(idea_set_encrypt_key);
387 
388 void
idea_set_decrypt_key(IDEA_KEY_SCHEDULE * ek,IDEA_KEY_SCHEDULE * dk)389 idea_set_decrypt_key(IDEA_KEY_SCHEDULE *ek, IDEA_KEY_SCHEDULE *dk)
390 {
391 	int r;
392 	IDEA_INT *fp, *tp, t;
393 
394 	tp = &(dk->data[0][0]);
395 	fp = &(ek->data[8][0]);
396 	for (r = 0; r < 9; r++)
397 	{
398 		*(tp++) = inverse(fp[0]);
399 		*(tp++) = ((int)(0x10000L - fp[2]) & 0xffff);
400 		*(tp++) = ((int)(0x10000L - fp[1]) & 0xffff);
401 		*(tp++) = inverse(fp[3]);
402 		if (r == 8)
403 			break;
404 		fp -= 6;
405 		*(tp++) = fp[4];
406 		*(tp++) = fp[5];
407 	}
408 
409 	tp = &(dk->data[0][0]);
410 	t = tp[1];
411 	tp[1] = tp[2];
412 	tp[2] = t;
413 
414 	t = tp[49];
415 	tp[49] = tp[50];
416 	tp[50] = t;
417 }
418 LCRYPTO_ALIAS(idea_set_decrypt_key);
419