1 /* $Id: acss.c,v 1.3 2005/07/17 07:04:47 djm Exp $ */
3 * Copyright (c) 2004 The OpenBSD project
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.
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.
19 #include <openssl/evp.h>
21 #if !defined(EVP_CTRL_SET_ACSS_MODE) && (OPENSSL_VERSION_NUMBER >= 0x00906000L)
26 static unsigned char sboxdec
[] = {
27 0x33, 0x73, 0x3b, 0x26, 0x63, 0x23, 0x6b, 0x76,
28 0x3e, 0x7e, 0x36, 0x2b, 0x6e, 0x2e, 0x66, 0x7b,
29 0xd3, 0x93, 0xdb, 0x06, 0x43, 0x03, 0x4b, 0x96,
30 0xde, 0x9e, 0xd6, 0x0b, 0x4e, 0x0e, 0x46, 0x9b,
31 0x57, 0x17, 0x5f, 0x82, 0xc7, 0x87, 0xcf, 0x12,
32 0x5a, 0x1a, 0x52, 0x8f, 0xca, 0x8a, 0xc2, 0x1f,
33 0xd9, 0x99, 0xd1, 0x00, 0x49, 0x09, 0x41, 0x90,
34 0xd8, 0x98, 0xd0, 0x01, 0x48, 0x08, 0x40, 0x91,
35 0x3d, 0x7d, 0x35, 0x24, 0x6d, 0x2d, 0x65, 0x74,
36 0x3c, 0x7c, 0x34, 0x25, 0x6c, 0x2c, 0x64, 0x75,
37 0xdd, 0x9d, 0xd5, 0x04, 0x4d, 0x0d, 0x45, 0x94,
38 0xdc, 0x9c, 0xd4, 0x05, 0x4c, 0x0c, 0x44, 0x95,
39 0x59, 0x19, 0x51, 0x80, 0xc9, 0x89, 0xc1, 0x10,
40 0x58, 0x18, 0x50, 0x81, 0xc8, 0x88, 0xc0, 0x11,
41 0xd7, 0x97, 0xdf, 0x02, 0x47, 0x07, 0x4f, 0x92,
42 0xda, 0x9a, 0xd2, 0x0f, 0x4a, 0x0a, 0x42, 0x9f,
43 0x53, 0x13, 0x5b, 0x86, 0xc3, 0x83, 0xcb, 0x16,
44 0x5e, 0x1e, 0x56, 0x8b, 0xce, 0x8e, 0xc6, 0x1b,
45 0xb3, 0xf3, 0xbb, 0xa6, 0xe3, 0xa3, 0xeb, 0xf6,
46 0xbe, 0xfe, 0xb6, 0xab, 0xee, 0xae, 0xe6, 0xfb,
47 0x37, 0x77, 0x3f, 0x22, 0x67, 0x27, 0x6f, 0x72,
48 0x3a, 0x7a, 0x32, 0x2f, 0x6a, 0x2a, 0x62, 0x7f,
49 0xb9, 0xf9, 0xb1, 0xa0, 0xe9, 0xa9, 0xe1, 0xf0,
50 0xb8, 0xf8, 0xb0, 0xa1, 0xe8, 0xa8, 0xe0, 0xf1,
51 0x5d, 0x1d, 0x55, 0x84, 0xcd, 0x8d, 0xc5, 0x14,
52 0x5c, 0x1c, 0x54, 0x85, 0xcc, 0x8c, 0xc4, 0x15,
53 0xbd, 0xfd, 0xb5, 0xa4, 0xed, 0xad, 0xe5, 0xf4,
54 0xbc, 0xfc, 0xb4, 0xa5, 0xec, 0xac, 0xe4, 0xf5,
55 0x39, 0x79, 0x31, 0x20, 0x69, 0x29, 0x61, 0x70,
56 0x38, 0x78, 0x30, 0x21, 0x68, 0x28, 0x60, 0x71,
57 0xb7, 0xf7, 0xbf, 0xa2, 0xe7, 0xa7, 0xef, 0xf2,
58 0xba, 0xfa, 0xb2, 0xaf, 0xea, 0xaa, 0xe2, 0xff
62 static unsigned char sboxenc
[] = {
63 0x33, 0x3b, 0x73, 0x15, 0x53, 0x5b, 0x13, 0x75,
64 0x3d, 0x35, 0x7d, 0x1b, 0x5d, 0x55, 0x1d, 0x7b,
65 0x67, 0x6f, 0x27, 0x81, 0xc7, 0xcf, 0x87, 0x21,
66 0x69, 0x61, 0x29, 0x8f, 0xc9, 0xc1, 0x89, 0x2f,
67 0xe3, 0xeb, 0xa3, 0x05, 0x43, 0x4b, 0x03, 0xa5,
68 0xed, 0xe5, 0xad, 0x0b, 0x4d, 0x45, 0x0d, 0xab,
69 0xea, 0xe2, 0xaa, 0x00, 0x4a, 0x42, 0x0a, 0xa0,
70 0xe8, 0xe0, 0xa8, 0x02, 0x48, 0x40, 0x08, 0xa2,
71 0x3e, 0x36, 0x7e, 0x14, 0x5e, 0x56, 0x1e, 0x74,
72 0x3c, 0x34, 0x7c, 0x16, 0x5c, 0x54, 0x1c, 0x76,
73 0x6a, 0x62, 0x2a, 0x80, 0xca, 0xc2, 0x8a, 0x20,
74 0x68, 0x60, 0x28, 0x82, 0xc8, 0xc0, 0x88, 0x22,
75 0xee, 0xe6, 0xae, 0x04, 0x4e, 0x46, 0x0e, 0xa4,
76 0xec, 0xe4, 0xac, 0x06, 0x4c, 0x44, 0x0c, 0xa6,
77 0xe7, 0xef, 0xa7, 0x01, 0x47, 0x4f, 0x07, 0xa1,
78 0xe9, 0xe1, 0xa9, 0x0f, 0x49, 0x41, 0x09, 0xaf,
79 0x63, 0x6b, 0x23, 0x85, 0xc3, 0xcb, 0x83, 0x25,
80 0x6d, 0x65, 0x2d, 0x8b, 0xcd, 0xc5, 0x8d, 0x2b,
81 0x37, 0x3f, 0x77, 0x11, 0x57, 0x5f, 0x17, 0x71,
82 0x39, 0x31, 0x79, 0x1f, 0x59, 0x51, 0x19, 0x7f,
83 0xb3, 0xbb, 0xf3, 0x95, 0xd3, 0xdb, 0x93, 0xf5,
84 0xbd, 0xb5, 0xfd, 0x9b, 0xdd, 0xd5, 0x9d, 0xfb,
85 0xba, 0xb2, 0xfa, 0x90, 0xda, 0xd2, 0x9a, 0xf0,
86 0xb8, 0xb0, 0xf8, 0x92, 0xd8, 0xd0, 0x98, 0xf2,
87 0x6e, 0x66, 0x2e, 0x84, 0xce, 0xc6, 0x8e, 0x24,
88 0x6c, 0x64, 0x2c, 0x86, 0xcc, 0xc4, 0x8c, 0x26,
89 0x3a, 0x32, 0x7a, 0x10, 0x5a, 0x52, 0x1a, 0x70,
90 0x38, 0x30, 0x78, 0x12, 0x58, 0x50, 0x18, 0x72,
91 0xbe, 0xb6, 0xfe, 0x94, 0xde, 0xd6, 0x9e, 0xf4,
92 0xbc, 0xb4, 0xfc, 0x96, 0xdc, 0xd4, 0x9c, 0xf6,
93 0xb7, 0xbf, 0xf7, 0x91, 0xd7, 0xdf, 0x97, 0xf1,
94 0xb9, 0xb1, 0xf9, 0x9f, 0xd9, 0xd1, 0x99, 0xff
97 static unsigned char reverse
[] = {
98 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
99 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
100 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
101 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
102 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
103 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
104 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
105 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
106 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
107 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
108 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
109 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
110 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
111 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
112 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
113 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
114 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
115 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
116 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
117 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
118 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
119 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
120 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
121 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
122 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
123 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
124 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
125 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
126 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
127 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
128 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
129 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff
133 * Two linear feedback shift registers are used:
135 * lfsr17: polynomial of degree 17, primitive modulo 2 (listed in Schneier)
137 * lfsr25: polynomial of degree 25, not know if primitive modulo 2
138 * x^13 + x^5 + x^4 + x^1 + 1
140 * Output bits are discarded, instead the feedback bits are added to produce
141 * the cipher stream. Depending on the mode, feedback bytes may be inverted
142 * bit-wise before addition.
144 * The lfsrs are seeded with bytes from the raw key:
146 * lfsr17: byte 0[0:7] at bit 9
147 * byte 1[0:7] at bit 0
149 * lfsr25: byte 2[0:4] at bit 16
150 * byte 2[5:7] at bit 22
151 * byte 3[0:7] at bit 8
152 * byte 4[0:7] at bit 0
154 * To prevent 0 cycles, 1's are inject at bit 8 in lfrs17 and bit 21 in
160 acss(ACSS_KEY
*key
, unsigned long len
, const unsigned char *in
,
164 unsigned long lfsr17tmp
, lfsr25tmp
, lfsrsumtmp
;
166 lfsrsumtmp
= lfsr17tmp
= lfsr25tmp
= 0;
168 /* keystream is sum of lfsrs */
169 for (i
= 0; i
< len
; i
++) {
170 lfsr17tmp
= key
->lfsr17
^ (key
->lfsr17
>> 14);
171 key
->lfsr17
= (key
->lfsr17
>> 8)
175 key
->lfsr17
&= 0x1ffff; /* 17 bit LFSR */
177 lfsr25tmp
= key
->lfsr25
180 ^ (key
->lfsr25
>> 12);
181 key
->lfsr25
= (key
->lfsr25
>> 8) ^ (lfsr25tmp
<< 17);
182 key
->lfsr25
&= 0x1ffffff; /* 25 bit LFSR */
184 lfsrsumtmp
= key
->lfsrsum
;
188 case ACSS_AUTHENTICATE
:
190 key
->lfsrsum
= 0xff & ~(key
->lfsr17
>> 9);
191 key
->lfsrsum
+= key
->lfsr25
>> 17;
193 case ACSS_SESSIONKEY
:
194 key
->lfsrsum
= key
->lfsr17
>> 9;
195 key
->lfsrsum
+= key
->lfsr25
>> 17;
198 key
->lfsrsum
= key
->lfsr17
>> 9;
199 key
->lfsrsum
+= 0xff & ~(key
->lfsr25
>> 17);
204 key
->lfsrsum
+= (lfsrsumtmp
>> 8);
207 out
[i
] = sboxenc
[(in
[i
] ^ key
->lfsrsum
) & 0xff];
209 out
[i
] = (sboxdec
[in
[i
]] ^ key
->lfsrsum
) & 0xff;
217 acss_seed(ACSS_KEY
*key
)
221 /* if available, mangle with subkey */
222 if (key
->subkey_avilable
) {
223 for (i
= 0; i
< ACSS_KEYSIZE
; i
++)
224 key
->seed
[i
] = reverse
[key
->data
[i
] ^ key
->subkey
[i
]];
226 for (i
= 0; i
< ACSS_KEYSIZE
; i
++)
227 key
->seed
[i
] = reverse
[key
->data
[i
]];
231 key
->lfsr17
= key
->seed
[1]
232 | (key
->seed
[0] << 9)
233 | (1 << 8); /* inject 1 at bit 9 */
234 key
->lfsr25
= key
->seed
[4]
235 | (key
->seed
[3] << 8)
236 | ((key
->seed
[2] & 0x1f) << 16)
237 | ((key
->seed
[2] & 0xe0) << 17)
238 | (1 << 21); /* inject 1 at bit 22 */
244 acss_setkey(ACSS_KEY
*key
, const unsigned char *data
, int enc
, int mode
)
246 memcpy(key
->data
, data
, sizeof(key
->data
));
247 memset(key
->subkey
, 0, sizeof(key
->subkey
));
252 key
->subkey_avilable
= 0;
258 acss_setsubkey(ACSS_KEY
*key
, const unsigned char *subkey
)
260 memcpy(key
->subkey
, subkey
, sizeof(key
->subkey
));
261 key
->subkey_avilable
= 1;