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