xref: /netbsd-src/crypto/external/bsd/heimdal/dist/lib/hcrypto/rc2.c (revision d3273b5b76f5afaafe308cead5511dbb8df8c5e9)
1*d3273b5bSchristos /*	$NetBSD: rc2.c,v 1.2 2017/01/28 21:31:47 christos Exp $	*/
2ca1c9b0cSelric 
3ca1c9b0cSelric /*
4ca1c9b0cSelric  * Copyright (c) 2004 Kungliga Tekniska Högskolan
5ca1c9b0cSelric  * (Royal Institute of Technology, Stockholm, Sweden).
6ca1c9b0cSelric  * All rights reserved.
7ca1c9b0cSelric  *
8ca1c9b0cSelric  * Redistribution and use in source and binary forms, with or without
9ca1c9b0cSelric  * modification, are permitted provided that the following conditions
10ca1c9b0cSelric  * are met:
11ca1c9b0cSelric  *
12ca1c9b0cSelric  * 1. Redistributions of source code must retain the above copyright
13ca1c9b0cSelric  *    notice, this list of conditions and the following disclaimer.
14ca1c9b0cSelric  *
15ca1c9b0cSelric  * 2. Redistributions in binary form must reproduce the above copyright
16ca1c9b0cSelric  *    notice, this list of conditions and the following disclaimer in the
17ca1c9b0cSelric  *    documentation and/or other materials provided with the distribution.
18ca1c9b0cSelric  *
19ca1c9b0cSelric  * 3. Neither the name of the Institute nor the names of its contributors
20ca1c9b0cSelric  *    may be used to endorse or promote products derived from this software
21ca1c9b0cSelric  *    without specific prior written permission.
22ca1c9b0cSelric  *
23ca1c9b0cSelric  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
24ca1c9b0cSelric  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25ca1c9b0cSelric  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26ca1c9b0cSelric  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
27ca1c9b0cSelric  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28ca1c9b0cSelric  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29ca1c9b0cSelric  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30ca1c9b0cSelric  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31ca1c9b0cSelric  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32ca1c9b0cSelric  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33ca1c9b0cSelric  * SUCH DAMAGE.
34ca1c9b0cSelric  */
35ca1c9b0cSelric 
36ca1c9b0cSelric #include <config.h>
37b9d004c6Schristos #include <krb5/roken.h>
38ca1c9b0cSelric 
39ca1c9b0cSelric #include "rc2.h"
40ca1c9b0cSelric 
41ca1c9b0cSelric /*
42ca1c9b0cSelric  * Implemented from Peter Gutmann's "Specification for Ron Rivests Cipher No.2"
43ca1c9b0cSelric  * rfc2268 and "On the Design and Security of RC2" was also useful.
44ca1c9b0cSelric  */
45ca1c9b0cSelric 
46ca1c9b0cSelric static unsigned int Sbox[256] = {
47ca1c9b0cSelric     0xd9, 0x78, 0xf9, 0xc4, 0x19, 0xdd, 0xb5, 0xed,
48ca1c9b0cSelric     0x28, 0xe9, 0xfd, 0x79, 0x4a, 0xa0, 0xd8, 0x9d,
49ca1c9b0cSelric     0xc6, 0x7e, 0x37, 0x83, 0x2b, 0x76, 0x53, 0x8e,
50ca1c9b0cSelric     0x62, 0x4c, 0x64, 0x88, 0x44, 0x8b, 0xfb, 0xa2,
51ca1c9b0cSelric     0x17, 0x9a, 0x59, 0xf5, 0x87, 0xb3, 0x4f, 0x13,
52ca1c9b0cSelric     0x61, 0x45, 0x6d, 0x8d, 0x09, 0x81, 0x7d, 0x32,
53ca1c9b0cSelric     0xbd, 0x8f, 0x40, 0xeb, 0x86, 0xb7, 0x7b, 0x0b,
54ca1c9b0cSelric     0xf0, 0x95, 0x21, 0x22, 0x5c, 0x6b, 0x4e, 0x82,
55ca1c9b0cSelric     0x54, 0xd6, 0x65, 0x93, 0xce, 0x60, 0xb2, 0x1c,
56ca1c9b0cSelric     0x73, 0x56, 0xc0, 0x14, 0xa7, 0x8c, 0xf1, 0xdc,
57ca1c9b0cSelric     0x12, 0x75, 0xca, 0x1f, 0x3b, 0xbe, 0xe4, 0xd1,
58ca1c9b0cSelric     0x42, 0x3d, 0xd4, 0x30, 0xa3, 0x3c, 0xb6, 0x26,
59ca1c9b0cSelric     0x6f, 0xbf, 0x0e, 0xda, 0x46, 0x69, 0x07, 0x57,
60ca1c9b0cSelric     0x27, 0xf2, 0x1d, 0x9b, 0xbc, 0x94, 0x43, 0x03,
61ca1c9b0cSelric     0xf8, 0x11, 0xc7, 0xf6, 0x90, 0xef, 0x3e, 0xe7,
62ca1c9b0cSelric     0x06, 0xc3, 0xd5, 0x2f, 0xc8, 0x66, 0x1e, 0xd7,
63ca1c9b0cSelric     0x08, 0xe8, 0xea, 0xde, 0x80, 0x52, 0xee, 0xf7,
64ca1c9b0cSelric     0x84, 0xaa, 0x72, 0xac, 0x35, 0x4d, 0x6a, 0x2a,
65ca1c9b0cSelric     0x96, 0x1a, 0xd2, 0x71, 0x5a, 0x15, 0x49, 0x74,
66ca1c9b0cSelric     0x4b, 0x9f, 0xd0, 0x5e, 0x04, 0x18, 0xa4, 0xec,
67ca1c9b0cSelric     0xc2, 0xe0, 0x41, 0x6e, 0x0f, 0x51, 0xcb, 0xcc,
68ca1c9b0cSelric     0x24, 0x91, 0xaf, 0x50, 0xa1, 0xf4, 0x70, 0x39,
69ca1c9b0cSelric     0x99, 0x7c, 0x3a, 0x85, 0x23, 0xb8, 0xb4, 0x7a,
70ca1c9b0cSelric     0xfc, 0x02, 0x36, 0x5b, 0x25, 0x55, 0x97, 0x31,
71ca1c9b0cSelric     0x2d, 0x5d, 0xfa, 0x98, 0xe3, 0x8a, 0x92, 0xae,
72ca1c9b0cSelric     0x05, 0xdf, 0x29, 0x10, 0x67, 0x6c, 0xba, 0xc9,
73ca1c9b0cSelric     0xd3, 0x00, 0xe6, 0xcf, 0xe1, 0x9e, 0xa8, 0x2c,
74ca1c9b0cSelric     0x63, 0x16, 0x01, 0x3f, 0x58, 0xe2, 0x89, 0xa9,
75ca1c9b0cSelric     0x0d, 0x38, 0x34, 0x1b, 0xab, 0x33, 0xff, 0xb0,
76ca1c9b0cSelric     0xbb, 0x48, 0x0c, 0x5f, 0xb9, 0xb1, 0xcd, 0x2e,
77ca1c9b0cSelric     0xc5, 0xf3, 0xdb, 0x47, 0xe5, 0xa5, 0x9c, 0x77,
78ca1c9b0cSelric     0x0a, 0xa6, 0x20, 0x68, 0xfe, 0x7f, 0xc1, 0xad
79ca1c9b0cSelric };
80ca1c9b0cSelric 
81ca1c9b0cSelric void
RC2_set_key(RC2_KEY * key,int len,const unsigned char * data,int bits)82ca1c9b0cSelric RC2_set_key(RC2_KEY *key, int len, const unsigned char *data, int bits)
83ca1c9b0cSelric {
84ca1c9b0cSelric     unsigned char k[128];
85ca1c9b0cSelric     int j, T8, TM;
86ca1c9b0cSelric 
87ca1c9b0cSelric     if (len <= 0)
88ca1c9b0cSelric 	abort();
89ca1c9b0cSelric     if (len > 128)
90ca1c9b0cSelric 	len = 128;
91ca1c9b0cSelric     if (bits <= 0 || bits > 1024)
92ca1c9b0cSelric 	bits = 1024;
93ca1c9b0cSelric 
94ca1c9b0cSelric     for (j = 0; j < len; j++)
95ca1c9b0cSelric 	k[j] = data[j];
96ca1c9b0cSelric     for (; j < 128; j++)
97ca1c9b0cSelric 	k[j] = Sbox[(k[j - len] + k[j - 1]) & 0xff];
98ca1c9b0cSelric 
99ca1c9b0cSelric     T8 = (bits + 7) / 8;
100ca1c9b0cSelric     j = (8*T8 - bits);
101ca1c9b0cSelric     TM = 0xff >> j;
102ca1c9b0cSelric 
103ca1c9b0cSelric     k[128 - T8] = Sbox[k[128 - T8] & TM];
104ca1c9b0cSelric 
105ca1c9b0cSelric     for (j = 127 - T8; j >= 0; j--)
106ca1c9b0cSelric 	k[j] = Sbox[k[j + 1] ^ k[j + T8]];
107ca1c9b0cSelric 
108ca1c9b0cSelric     for (j = 0; j < 64; j++)
109ca1c9b0cSelric 	key->data[j] = k[(j * 2) + 0] | (k[(j * 2) + 1] << 8);
110ca1c9b0cSelric     memset(k, 0, sizeof(k));
111ca1c9b0cSelric }
112ca1c9b0cSelric 
113ca1c9b0cSelric #define ROT16L(w,n)  ((w<<n)|(w>>(16-n)))
114ca1c9b0cSelric #define ROT16R(w,n)  ((w>>n)|(w<<(16-n)))
115ca1c9b0cSelric 
116ca1c9b0cSelric void
RC2_encryptc(unsigned char * in,unsigned char * out,const RC2_KEY * key)117ca1c9b0cSelric RC2_encryptc(unsigned char *in, unsigned char *out, const RC2_KEY *key)
118ca1c9b0cSelric {
119ca1c9b0cSelric     int i, j;
120ca1c9b0cSelric     int w0, w1, w2, w3;
121ca1c9b0cSelric     int t0, t1, t2, t3;
122ca1c9b0cSelric 
123ca1c9b0cSelric     w0 = in[0] | (in[1] << 8);
124ca1c9b0cSelric     w1 = in[2] | (in[3] << 8);
125ca1c9b0cSelric     w2 = in[4] | (in[5] << 8);
126ca1c9b0cSelric     w3 = in[6] | (in[7] << 8);
127ca1c9b0cSelric 
128ca1c9b0cSelric     for (i = 0; i < 16; i++) {
129ca1c9b0cSelric 	j = i * 4;
130ca1c9b0cSelric 	t0 = (w0 + (w1 & ~w3) + (w2 & w3) + key->data[j + 0]) & 0xffff;
131ca1c9b0cSelric 	w0 = ROT16L(t0, 1);
132ca1c9b0cSelric 	t1 = (w1 + (w2 & ~w0) + (w3 & w0) + key->data[j + 1]) & 0xffff;
133ca1c9b0cSelric 	w1 = ROT16L(t1, 2);
134ca1c9b0cSelric 	t2 = (w2 + (w3 & ~w1) + (w0 & w1) + key->data[j + 2]) & 0xffff;
135ca1c9b0cSelric 	w2 = ROT16L(t2, 3);
136ca1c9b0cSelric 	t3 = (w3 + (w0 & ~w2) + (w1 & w2) + key->data[j + 3]) & 0xffff;
137ca1c9b0cSelric 	w3 = ROT16L(t3, 5);
138ca1c9b0cSelric 	if(i == 4 || i == 10) {
139ca1c9b0cSelric 	    w0 += key->data[w3 & 63];
140ca1c9b0cSelric 	    w1 += key->data[w0 & 63];
141ca1c9b0cSelric 	    w2 += key->data[w1 & 63];
142ca1c9b0cSelric 	    w3 += key->data[w2 & 63];
143ca1c9b0cSelric 	}
144ca1c9b0cSelric     }
145ca1c9b0cSelric 
146ca1c9b0cSelric     out[0] = w0 & 0xff;
147ca1c9b0cSelric     out[1] = (w0 >> 8) & 0xff;
148ca1c9b0cSelric     out[2] = w1 & 0xff;
149ca1c9b0cSelric     out[3] = (w1 >> 8) & 0xff;
150ca1c9b0cSelric     out[4] = w2 & 0xff;
151ca1c9b0cSelric     out[5] = (w2 >> 8) & 0xff;
152ca1c9b0cSelric     out[6] = w3 & 0xff;
153ca1c9b0cSelric     out[7] = (w3 >> 8) & 0xff;
154ca1c9b0cSelric }
155ca1c9b0cSelric 
156ca1c9b0cSelric void
RC2_decryptc(unsigned char * in,unsigned char * out,const RC2_KEY * key)157ca1c9b0cSelric RC2_decryptc(unsigned char *in, unsigned char *out, const RC2_KEY *key)
158ca1c9b0cSelric {
159ca1c9b0cSelric     int i, j;
160ca1c9b0cSelric     int w0, w1, w2, w3;
161ca1c9b0cSelric     int t0, t1, t2, t3;
162ca1c9b0cSelric 
163ca1c9b0cSelric     w0 = in[0] | (in[1] << 8);
164ca1c9b0cSelric     w1 = in[2] | (in[3] << 8);
165ca1c9b0cSelric     w2 = in[4] | (in[5] << 8);
166ca1c9b0cSelric     w3 = in[6] | (in[7] << 8);
167ca1c9b0cSelric 
168ca1c9b0cSelric     for (i = 15; i >= 0; i--) {
169ca1c9b0cSelric 	j = i * 4;
170ca1c9b0cSelric 
171ca1c9b0cSelric 	if(i == 4 || i == 10) {
172ca1c9b0cSelric 	    w3 = (w3 - key->data[w2 & 63]) & 0xffff;
173ca1c9b0cSelric 	    w2 = (w2 - key->data[w1 & 63]) & 0xffff;
174ca1c9b0cSelric 	    w1 = (w1 - key->data[w0 & 63]) & 0xffff;
175ca1c9b0cSelric 	    w0 = (w0 - key->data[w3 & 63]) & 0xffff;
176ca1c9b0cSelric 	}
177ca1c9b0cSelric 
178ca1c9b0cSelric 	t3 = ROT16R(w3, 5);
179ca1c9b0cSelric 	w3 = (t3 - (w0 & ~w2) - (w1 & w2) - key->data[j + 3]) & 0xffff;
180ca1c9b0cSelric 	t2 = ROT16R(w2, 3);
181ca1c9b0cSelric 	w2 = (t2 - (w3 & ~w1) - (w0 & w1) - key->data[j + 2]) & 0xffff;
182ca1c9b0cSelric 	t1 = ROT16R(w1, 2);
183ca1c9b0cSelric 	w1 = (t1 - (w2 & ~w0) - (w3 & w0) - key->data[j + 1]) & 0xffff;
184ca1c9b0cSelric 	t0 = ROT16R(w0, 1);
185ca1c9b0cSelric 	w0 = (t0 - (w1 & ~w3) - (w2 & w3) - key->data[j + 0]) & 0xffff;
186ca1c9b0cSelric 
187ca1c9b0cSelric     }
188ca1c9b0cSelric     out[0] = w0 & 0xff;
189ca1c9b0cSelric     out[1] = (w0 >> 8) & 0xff;
190ca1c9b0cSelric     out[2] = w1 & 0xff;
191ca1c9b0cSelric     out[3] = (w1 >> 8) & 0xff;
192ca1c9b0cSelric     out[4] = w2 & 0xff;
193ca1c9b0cSelric     out[5] = (w2 >> 8) & 0xff;
194ca1c9b0cSelric     out[6] = w3 & 0xff;
195ca1c9b0cSelric     out[7] = (w3 >> 8) & 0xff;
196ca1c9b0cSelric }
197ca1c9b0cSelric 
198ca1c9b0cSelric void
RC2_cbc_encrypt(const unsigned char * in,unsigned char * out,long size,RC2_KEY * key,unsigned char * iv,int forward_encrypt)199ca1c9b0cSelric RC2_cbc_encrypt(const unsigned char *in, unsigned char *out, long size,
200ca1c9b0cSelric 		RC2_KEY *key, unsigned char *iv, int forward_encrypt)
201ca1c9b0cSelric {
202ca1c9b0cSelric     unsigned char tmp[RC2_BLOCK_SIZE];
203ca1c9b0cSelric     int i;
204ca1c9b0cSelric 
205ca1c9b0cSelric     if (forward_encrypt) {
206ca1c9b0cSelric 	while (size >= RC2_BLOCK_SIZE) {
207ca1c9b0cSelric 	    for (i = 0; i < RC2_BLOCK_SIZE; i++)
208ca1c9b0cSelric 		tmp[i] = in[i] ^ iv[i];
209ca1c9b0cSelric 	    RC2_encryptc(tmp, out, key);
210ca1c9b0cSelric 	    memcpy(iv, out, RC2_BLOCK_SIZE);
211ca1c9b0cSelric 	    size -= RC2_BLOCK_SIZE;
212ca1c9b0cSelric 	    in += RC2_BLOCK_SIZE;
213ca1c9b0cSelric 	    out += RC2_BLOCK_SIZE;
214ca1c9b0cSelric 	}
215ca1c9b0cSelric 	if (size) {
216ca1c9b0cSelric 	    for (i = 0; i < size; i++)
217ca1c9b0cSelric 		tmp[i] = in[i] ^ iv[i];
218ca1c9b0cSelric 	    for (i = size; i < RC2_BLOCK_SIZE; i++)
219ca1c9b0cSelric 		tmp[i] = iv[i];
220ca1c9b0cSelric 	    RC2_encryptc(tmp, out, key);
221ca1c9b0cSelric 	    memcpy(iv, out, RC2_BLOCK_SIZE);
222ca1c9b0cSelric 	}
223ca1c9b0cSelric     } else {
224ca1c9b0cSelric 	while (size >= RC2_BLOCK_SIZE) {
225ca1c9b0cSelric 	    memcpy(tmp, in, RC2_BLOCK_SIZE);
226ca1c9b0cSelric 	    RC2_decryptc(tmp, out, key);
227ca1c9b0cSelric 	    for (i = 0; i < RC2_BLOCK_SIZE; i++)
228ca1c9b0cSelric 		out[i] ^= iv[i];
229ca1c9b0cSelric 	    memcpy(iv, tmp, RC2_BLOCK_SIZE);
230ca1c9b0cSelric 	    size -= RC2_BLOCK_SIZE;
231ca1c9b0cSelric 	    in += RC2_BLOCK_SIZE;
232ca1c9b0cSelric 	    out += RC2_BLOCK_SIZE;
233ca1c9b0cSelric 	}
234ca1c9b0cSelric 	if (size) {
235ca1c9b0cSelric 	    memcpy(tmp, in, RC2_BLOCK_SIZE);
236ca1c9b0cSelric 	    RC2_decryptc(tmp, out, key);
237ca1c9b0cSelric 	    for (i = 0; i < size; i++)
238ca1c9b0cSelric 		out[i] ^= iv[i];
239ca1c9b0cSelric 	    memcpy(iv, tmp, RC2_BLOCK_SIZE);
240ca1c9b0cSelric 	}
241ca1c9b0cSelric     }
242ca1c9b0cSelric }
243