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