xref: /minix3/crypto/external/bsd/heimdal/dist/lib/hcrypto/rc2.c (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
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