xref: /inferno-os/libsec/port/idea.c (revision 37da2899f40661e3e9631e497da8dc59b971cbd0)
1 #include "os.h"
2 #include "mp.h"
3 #include "libsec.h"
4 
5 #define KEYLEN	52
6 
7 #define	MODA	0x10000
8 #define	MODM	0x10001
9 #define	MASKA	(MODA-1)
10 
11 #define 	OP1(x, y)		((x) ^ (y))
12 #define	OP2(x, y)		(((x) + (y)) & MASKA)
13 #define 	OP3(x, y)		mod(x, y)
14 
15 #define	OP2INV(x)	(-(x))
16 #define	OP3INV(x)	inv(x)
17 
18 #define BIGEND(k, i)	((k[i]<<8)|k[i+1])
19 #define MSB(x)		((x)>>8)
20 #define LSB(x)		((x)&0xff)
21 
22 static ushort
mod(ushort x,ushort y)23 mod(ushort x, ushort y)
24 {
25 	ushort q, r;
26 	uint z;
27 
28 	if (x == 0)
29 		return 1-y;
30 	if (y == 0)
31 		return 1-x;
32 	z = (uint)x*(uint)y;
33 	q = z >> 16;
34 	r = z & MASKA;
35 	return r-q+(r<q);
36 }
37 
38 static ushort
inv(ushort x)39 inv(ushort x)
40 {
41 	int q, r0, r1, r2, v0, v1, v2;
42 
43 	if (x <= 1)
44 		return x;
45 	r0 = MODM;
46 	r1 = x;
47 	v0 = 0;
48 	v1 = 1;
49 	while (r1 != 0) {
50 		q = r0/r1;
51 		r2 = r0-q*r1;
52 		v2 = v0-q*v1;
53 		r0 = r1;
54 		r1 = r2;
55 		v0 = v1;
56 		v1 = v2;
57 	}
58 	if (v0 < 0)
59 		v0 += MODM;
60 	return v0 & MASKA;
61 }
62 
63 static void
idea_key_setup_decrypt(ushort ek[KEYLEN],ushort dk[KEYLEN])64 idea_key_setup_decrypt(ushort ek[KEYLEN], ushort dk[KEYLEN])
65 {
66 	int i;
67 
68 	for (i = 0; i < 54; i += 6) {
69 		dk[i] = OP3INV(ek[48-i]);
70 		dk[i+1] = OP2INV(ek[50-i]);
71 		dk[i+2] = OP2INV(ek[49-i]);
72 		dk[i+3] = OP3INV(ek[51-i]);
73 		if (i < 48) {
74 			dk[i+4] = ek[46-i];
75 			dk[i+5] = ek[47-i];
76 		}
77 	}
78 }
79 
80 void
idea_key_setup(uchar key[16],ushort ek[2* KEYLEN])81 idea_key_setup(uchar key[16], ushort ek[2*KEYLEN])
82 {
83 	int i, j;
84 	ushort tmp, *e = ek;
85 
86 	for (i = 0; i < 8; i++)
87 		ek[i] = BIGEND(key, 2*i);
88 	for (i = 8, j = 1; i < KEYLEN; i++, j++) {
89 		ek[i] = (e[j&7]<<9)|(e[(j+1)&7]>>7);
90 		if (((i+1) & 7) == 0)
91 			e += 8;
92 	}
93 	tmp = ek[49];
94 	ek[49] = ek[50];
95 	ek[50] = tmp;
96 	idea_key_setup_decrypt(ek, &ek[KEYLEN]);
97 }
98 
99 void
idea_cipher(ushort key[2* KEYLEN],uchar text[8],int decrypting)100 idea_cipher(ushort key[2*KEYLEN], uchar text[8], int decrypting)
101 {
102 	int i;
103 	ushort *k;
104 	ushort x[4];
105 	ushort tmp, yout, zout;
106 
107 	k = decrypting ? &key[KEYLEN] : key;
108 	for (i = 0; i < 4; i++)
109 		x[i] = BIGEND(text, 2*i);
110 	for (i = 0; i < 17; i++) {
111 		if (!(i&1)) {		/* odd round */
112 			x[0] = OP3(x[0], k[3*i]);
113 			tmp = OP2(x[2], k[3*i+2]);
114 			x[2] = OP2(x[1], k[3*i+1]);
115 			x[3] = OP3(x[3], k[3*i+3]);
116 			x[1] = tmp;
117 		}
118 		else {
119 			tmp = OP3(k[3*i+1], OP1(x[0], x[1]));
120 			yout = OP3(OP2(tmp, OP1(x[2], x[3])), k[3*i+2]);
121 			zout = OP2(tmp, yout);
122 			x[0] = OP1(x[0], yout);
123 			x[1] = OP1(x[1], yout);
124 			x[2] = OP1(x[2], zout);
125 			x[3] = OP1(x[3], zout);
126 		}
127 	}
128 	for (i = 0; i < 4; i++) {
129 		text[2*i] = MSB(x[i]);
130 		text[2*i+1] = LSB(x[i]);
131 	}
132 }
133 
134 void
setupIDEAstate(IDEAstate * s,uchar key[16],uchar * ivec)135 setupIDEAstate(IDEAstate *s, uchar key[16], uchar *ivec)
136 {
137 	memset(s, 0, sizeof(*s));
138 	memmove(s->key, key, sizeof(s->key));
139 	idea_key_setup(key, s->edkey);
140 	if(ivec)
141 		memmove(s->ivec, ivec, 8);
142 }
143 
144 /*
145 void
146 main()
147 {
148 	uchar key[] = { 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x04,
149 			        0x00, 0x05, 0x00, 0x06, 0x00, 0x07, 0x00, 0x08 };
150 	uchar plain[] = { 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x03 };
151 	uchar cipher[] = { 0x11, 0xFB, 0xED, 0x2B, 0x01, 0x98, 0x6D, 0xE5 };
152 	ushort edkey[2*KEYLEN];
153 	uchar tmp[8];
154 
155 	memcpy(tmp, plain, 8);
156 	idea_key_setup(key, edkey);
157 	idea_cipher(edkey, tmp, 0);
158 	if (memcmp(tmp, cipher, 8)) {
159 		print("encrypt wrong\n");
160 		exits("");
161 	}
162 	idea_cipher(edkey, tmp, 1);
163 	if (memcmp(tmp, plain, 8)) {
164 		print("decrypt wrong\n");
165 		exits("");
166 	}
167 }
168 */
169