• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*	$Id: acss.c,v 1.4 2006/07/24 04:51:01 djm Exp $ */
2 /*
3  * Copyright (c) 2004 The OpenBSD project
4  *
5  * Permission to use, copy, modify, and distribute this software for any
6  * purpose with or without fee is hereby granted, provided that the above
7  * copyright notice and this permission notice appear in all copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16  */
17 
18 #include "includes.h"
19 
20 #include <string.h>
21 
22 #include <openssl/evp.h>
23 
24 #if !defined(EVP_CTRL_SET_ACSS_MODE) && (OPENSSL_VERSION_NUMBER >= 0x00906000L)
25 
26 #include "acss.h"
27 
28 /* decryption sbox */
29 static unsigned char sboxdec[] = {
30 	0x33, 0x73, 0x3b, 0x26, 0x63, 0x23, 0x6b, 0x76,
31 	0x3e, 0x7e, 0x36, 0x2b, 0x6e, 0x2e, 0x66, 0x7b,
32 	0xd3, 0x93, 0xdb, 0x06, 0x43, 0x03, 0x4b, 0x96,
33 	0xde, 0x9e, 0xd6, 0x0b, 0x4e, 0x0e, 0x46, 0x9b,
34 	0x57, 0x17, 0x5f, 0x82, 0xc7, 0x87, 0xcf, 0x12,
35 	0x5a, 0x1a, 0x52, 0x8f, 0xca, 0x8a, 0xc2, 0x1f,
36 	0xd9, 0x99, 0xd1, 0x00, 0x49, 0x09, 0x41, 0x90,
37 	0xd8, 0x98, 0xd0, 0x01, 0x48, 0x08, 0x40, 0x91,
38 	0x3d, 0x7d, 0x35, 0x24, 0x6d, 0x2d, 0x65, 0x74,
39 	0x3c, 0x7c, 0x34, 0x25, 0x6c, 0x2c, 0x64, 0x75,
40 	0xdd, 0x9d, 0xd5, 0x04, 0x4d, 0x0d, 0x45, 0x94,
41 	0xdc, 0x9c, 0xd4, 0x05, 0x4c, 0x0c, 0x44, 0x95,
42 	0x59, 0x19, 0x51, 0x80, 0xc9, 0x89, 0xc1, 0x10,
43 	0x58, 0x18, 0x50, 0x81, 0xc8, 0x88, 0xc0, 0x11,
44 	0xd7, 0x97, 0xdf, 0x02, 0x47, 0x07, 0x4f, 0x92,
45 	0xda, 0x9a, 0xd2, 0x0f, 0x4a, 0x0a, 0x42, 0x9f,
46 	0x53, 0x13, 0x5b, 0x86, 0xc3, 0x83, 0xcb, 0x16,
47 	0x5e, 0x1e, 0x56, 0x8b, 0xce, 0x8e, 0xc6, 0x1b,
48 	0xb3, 0xf3, 0xbb, 0xa6, 0xe3, 0xa3, 0xeb, 0xf6,
49 	0xbe, 0xfe, 0xb6, 0xab, 0xee, 0xae, 0xe6, 0xfb,
50 	0x37, 0x77, 0x3f, 0x22, 0x67, 0x27, 0x6f, 0x72,
51 	0x3a, 0x7a, 0x32, 0x2f, 0x6a, 0x2a, 0x62, 0x7f,
52 	0xb9, 0xf9, 0xb1, 0xa0, 0xe9, 0xa9, 0xe1, 0xf0,
53 	0xb8, 0xf8, 0xb0, 0xa1, 0xe8, 0xa8, 0xe0, 0xf1,
54 	0x5d, 0x1d, 0x55, 0x84, 0xcd, 0x8d, 0xc5, 0x14,
55 	0x5c, 0x1c, 0x54, 0x85, 0xcc, 0x8c, 0xc4, 0x15,
56 	0xbd, 0xfd, 0xb5, 0xa4, 0xed, 0xad, 0xe5, 0xf4,
57 	0xbc, 0xfc, 0xb4, 0xa5, 0xec, 0xac, 0xe4, 0xf5,
58 	0x39, 0x79, 0x31, 0x20, 0x69, 0x29, 0x61, 0x70,
59 	0x38, 0x78, 0x30, 0x21, 0x68, 0x28, 0x60, 0x71,
60 	0xb7, 0xf7, 0xbf, 0xa2, 0xe7, 0xa7, 0xef, 0xf2,
61 	0xba, 0xfa, 0xb2, 0xaf, 0xea, 0xaa, 0xe2, 0xff
62 };
63 
64 /* encryption sbox */
65 static unsigned char sboxenc[] = {
66 	0x33, 0x3b, 0x73, 0x15, 0x53, 0x5b, 0x13, 0x75,
67 	0x3d, 0x35, 0x7d, 0x1b, 0x5d, 0x55, 0x1d, 0x7b,
68 	0x67, 0x6f, 0x27, 0x81, 0xc7, 0xcf, 0x87, 0x21,
69 	0x69, 0x61, 0x29, 0x8f, 0xc9, 0xc1, 0x89, 0x2f,
70 	0xe3, 0xeb, 0xa3, 0x05, 0x43, 0x4b, 0x03, 0xa5,
71 	0xed, 0xe5, 0xad, 0x0b, 0x4d, 0x45, 0x0d, 0xab,
72 	0xea, 0xe2, 0xaa, 0x00, 0x4a, 0x42, 0x0a, 0xa0,
73 	0xe8, 0xe0, 0xa8, 0x02, 0x48, 0x40, 0x08, 0xa2,
74 	0x3e, 0x36, 0x7e, 0x14, 0x5e, 0x56, 0x1e, 0x74,
75 	0x3c, 0x34, 0x7c, 0x16, 0x5c, 0x54, 0x1c, 0x76,
76 	0x6a, 0x62, 0x2a, 0x80, 0xca, 0xc2, 0x8a, 0x20,
77 	0x68, 0x60, 0x28, 0x82, 0xc8, 0xc0, 0x88, 0x22,
78 	0xee, 0xe6, 0xae, 0x04, 0x4e, 0x46, 0x0e, 0xa4,
79 	0xec, 0xe4, 0xac, 0x06, 0x4c, 0x44, 0x0c, 0xa6,
80 	0xe7, 0xef, 0xa7, 0x01, 0x47, 0x4f, 0x07, 0xa1,
81 	0xe9, 0xe1, 0xa9, 0x0f, 0x49, 0x41, 0x09, 0xaf,
82 	0x63, 0x6b, 0x23, 0x85, 0xc3, 0xcb, 0x83, 0x25,
83 	0x6d, 0x65, 0x2d, 0x8b, 0xcd, 0xc5, 0x8d, 0x2b,
84 	0x37, 0x3f, 0x77, 0x11, 0x57, 0x5f, 0x17, 0x71,
85 	0x39, 0x31, 0x79, 0x1f, 0x59, 0x51, 0x19, 0x7f,
86 	0xb3, 0xbb, 0xf3, 0x95, 0xd3, 0xdb, 0x93, 0xf5,
87 	0xbd, 0xb5, 0xfd, 0x9b, 0xdd, 0xd5, 0x9d, 0xfb,
88 	0xba, 0xb2, 0xfa, 0x90, 0xda, 0xd2, 0x9a, 0xf0,
89 	0xb8, 0xb0, 0xf8, 0x92, 0xd8, 0xd0, 0x98, 0xf2,
90 	0x6e, 0x66, 0x2e, 0x84, 0xce, 0xc6, 0x8e, 0x24,
91 	0x6c, 0x64, 0x2c, 0x86, 0xcc, 0xc4, 0x8c, 0x26,
92 	0x3a, 0x32, 0x7a, 0x10, 0x5a, 0x52, 0x1a, 0x70,
93 	0x38, 0x30, 0x78, 0x12, 0x58, 0x50, 0x18, 0x72,
94 	0xbe, 0xb6, 0xfe, 0x94, 0xde, 0xd6, 0x9e, 0xf4,
95 	0xbc, 0xb4, 0xfc, 0x96, 0xdc, 0xd4, 0x9c, 0xf6,
96 	0xb7, 0xbf, 0xf7, 0x91, 0xd7, 0xdf, 0x97, 0xf1,
97 	0xb9, 0xb1, 0xf9, 0x9f, 0xd9, 0xd1, 0x99, 0xff
98 };
99 
100 static unsigned char reverse[] = {
101 	0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
102 	0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
103 	0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
104 	0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
105 	0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
106 	0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
107 	0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
108 	0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
109 	0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
110 	0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
111 	0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
112 	0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
113 	0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
114 	0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
115 	0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
116 	0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
117 	0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
118 	0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
119 	0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
120 	0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
121 	0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
122 	0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
123 	0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
124 	0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
125 	0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
126 	0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
127 	0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
128 	0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
129 	0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
130 	0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
131 	0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
132 	0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff
133 };
134 
135 /*
136  * Two linear feedback shift registers are used:
137  *
138  * lfsr17:  polynomial of degree 17, primitive modulo 2 (listed in Schneier)
139  *          x^15 + x + 1
140  * lfsr25:  polynomial of degree 25, not know if primitive modulo 2
141  *          x^13 + x^5 + x^4 + x^1 + 1
142  *
143  * Output bits are discarded, instead the feedback bits are added to produce
144  * the cipher stream.  Depending on the mode, feedback bytes may be inverted
145  * bit-wise before addition.
146  *
147  * The lfsrs are seeded with bytes from the raw key:
148  *
149  * lfsr17:  byte 0[0:7] at bit 9
150  *          byte 1[0:7] at bit 0
151  *
152  * lfsr25:  byte 2[0:4] at bit 16
153  *          byte 2[5:7] at bit 22
154  *          byte 3[0:7] at bit 8
155  *          byte 4[0:7] at bit 0
156  *
157  * To prevent 0 cycles, 1's are inject at bit 8 in lfrs17 and bit 21 in
158  * lfsr25.
159  *
160  */
161 
162 int
acss(ACSS_KEY * key,unsigned long len,const unsigned char * in,unsigned char * out)163 acss(ACSS_KEY *key, unsigned long len, const unsigned char *in,
164     unsigned char *out)
165 {
166 	unsigned long i;
167 	unsigned long lfsr17tmp, lfsr25tmp, lfsrsumtmp;
168 
169 	lfsrsumtmp = lfsr17tmp = lfsr25tmp = 0;
170 
171 	/* keystream is sum of lfsrs */
172 	for (i = 0; i < len; i++) {
173 		lfsr17tmp = key->lfsr17 ^ (key->lfsr17 >> 14);
174 		key->lfsr17 = (key->lfsr17 >> 8)
175 			^ (lfsr17tmp << 9)
176 			^ (lfsr17tmp << 12)
177 			^ (lfsr17tmp << 15);
178 		key->lfsr17 &= 0x1ffff;	/* 17 bit LFSR */
179 
180 		lfsr25tmp = key->lfsr25
181 			^ (key->lfsr25 >> 3)
182 			^ (key->lfsr25 >> 4)
183 			^ (key->lfsr25 >> 12);
184 		key->lfsr25 = (key->lfsr25 >> 8) ^ (lfsr25tmp << 17);
185 		key->lfsr25 &= 0x1ffffff;	/* 25 bit LFSR */
186 
187 		lfsrsumtmp = key->lfsrsum;
188 
189 		/* addition */
190 		switch (key->mode) {
191 		case ACSS_AUTHENTICATE:
192 		case ACSS_DATA:
193 			key->lfsrsum = 0xff & ~(key->lfsr17 >> 9);
194 			key->lfsrsum += key->lfsr25 >> 17;
195 			break;
196 		case ACSS_SESSIONKEY:
197 			key->lfsrsum = key->lfsr17 >> 9;
198 			key->lfsrsum += key->lfsr25 >> 17;
199 			break;
200 		case ACSS_TITLEKEY:
201 			key->lfsrsum = key->lfsr17 >> 9;
202 			key->lfsrsum += 0xff & ~(key->lfsr25 >> 17);
203 			break;
204 		default:
205 			return 1;
206 		}
207 		key->lfsrsum += (lfsrsumtmp >> 8);
208 
209 		if (key->encrypt) {
210 			out[i] = sboxenc[(in[i] ^ key->lfsrsum) & 0xff];
211 		} else {
212 			out[i] = (sboxdec[in[i]] ^ key->lfsrsum) & 0xff;
213 		}
214 	}
215 
216 	return 0;
217 }
218 
219 static void
acss_seed(ACSS_KEY * key)220 acss_seed(ACSS_KEY *key)
221 {
222 	int i;
223 
224 	/* if available, mangle with subkey */
225 	if (key->subkey_avilable) {
226 		for (i = 0; i < ACSS_KEYSIZE; i++)
227 			key->seed[i] = reverse[key->data[i] ^ key->subkey[i]];
228 	} else {
229 		for (i = 0; i < ACSS_KEYSIZE; i++)
230 			key->seed[i] = reverse[key->data[i]];
231 	}
232 
233 	/* seed lfsrs */
234 	key->lfsr17 = key->seed[1]
235 		| (key->seed[0] << 9)
236 		| (1 << 8);	/* inject 1 at bit 9 */
237 	key->lfsr25 = key->seed[4]
238 		| (key->seed[3] << 8)
239 		| ((key->seed[2] & 0x1f) << 16)
240 		| ((key->seed[2] & 0xe0) << 17)
241 			| (1 << 21);	/* inject 1 at bit 22 */
242 
243 	key->lfsrsum = 0;
244 }
245 
246 void
acss_setkey(ACSS_KEY * key,const unsigned char * data,int enc,int mode)247 acss_setkey(ACSS_KEY *key, const unsigned char *data, int enc, int mode)
248 {
249 	memcpy(key->data, data, sizeof(key->data));
250 	memset(key->subkey, 0, sizeof(key->subkey));
251 
252 	if (enc != -1)
253 		key->encrypt = enc;
254 	key->mode = mode;
255 	key->subkey_avilable = 0;
256 
257 	acss_seed(key);
258 }
259 
260 void
acss_setsubkey(ACSS_KEY * key,const unsigned char * subkey)261 acss_setsubkey(ACSS_KEY *key, const unsigned char *subkey)
262 {
263 	memcpy(key->subkey, subkey, sizeof(key->subkey));
264 	key->subkey_avilable = 1;
265 	acss_seed(key);
266 }
267 #endif
268