1 /****************************************************************************
2 * *
3 * cryptlib RC4 Encryption Routines *
4 * Copyright Peter Gutmann 1994-2005 *
5 * *
6 ****************************************************************************/
7
8 #if defined( INC_ALL )
9 #include "crypt.h"
10 #include "context.h"
11 #include "rc4.h"
12 #else
13 #include "crypt.h"
14 #include "context/context.h"
15 #include "crypt/rc4.h"
16 #endif /* Compiler-specific includes */
17
18 #ifdef USE_RC4
19
20 /* The size of the expanded RC4 keys */
21
22 #define RC4_EXPANDED_KEYSIZE sizeof( RC4_KEY )
23
24 /****************************************************************************
25 * *
26 * RC4 Self-test Routines *
27 * *
28 ****************************************************************************/
29
30 #ifndef CONFIG_NO_SELFTEST
31
32 /* RC4 test vectors from the BSAFE implementation */
33
34 static const BYTE FAR_BSS testRC4key1[] =
35 { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF };
36 static const BYTE FAR_BSS testRC4plaintext1[] =
37 { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF };
38 static const BYTE FAR_BSS testRC4ciphertext1[] =
39 { 0x75, 0xB7, 0x87, 0x80, 0x99, 0xE0, 0xC5, 0x96 };
40
41 static const BYTE FAR_BSS testRC4key2[] =
42 { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF };
43 static const BYTE FAR_BSS testRC4plaintext2[] =
44 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
45 static const BYTE FAR_BSS testRC4ciphertext2[] =
46 { 0x74, 0x94, 0xC2, 0xE7, 0x10, 0x4B, 0x08, 0x79 };
47
48 static const BYTE FAR_BSS testRC4key3[] =
49 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
50 static const BYTE FAR_BSS testRC4plaintext3[] =
51 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
52 static const BYTE FAR_BSS testRC4ciphertext3[] =
53 { 0xDE, 0x18, 0x89, 0x41, 0xA3, 0x37, 0x5D, 0x3A };
54
55 static const BYTE FAR_BSS testRC4key4[] =
56 { 0xEF, 0x01, 0x23, 0x45 };
57 static const BYTE FAR_BSS testRC4plaintext4[] =
58 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
59 static const BYTE FAR_BSS testRC4ciphertext4[] =
60 { 0xD6, 0xA1, 0x41, 0xA7, 0xEC, 0x3C, 0x38, 0xDF, 0xBD, 0x61 };
61
62 static const BYTE FAR_BSS testRC4key5[] =
63 { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF };
64 static const BYTE FAR_BSS testRC4plaintext5[] =
65 { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
66 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
67 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
68 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
69 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
70 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
71 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
72 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
73 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
74 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
75 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
76 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
77 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
78 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
79 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
80 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
81 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
82 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
83 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
84 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
85 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
86 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
87 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
88 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
89 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
90 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
91 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
92 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
93 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
94 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
95 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
96 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
97 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
98 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
99 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
100 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
101 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
102 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
103 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
104 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
105 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
106 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
107 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
108 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
109 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
110 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
111 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
112 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
113 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
114 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
115 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
116 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
117 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
118 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
119 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
120 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
121 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
122 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
123 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
124 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
125 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
126 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
127 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
128 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 };
129 static const BYTE FAR_BSS testRC4ciphertext5[] =
130 { 0x75, 0x95, 0xC3, 0xE6, 0x11, 0x4A, 0x09, 0x78,
131 0x0C, 0x4A, 0xD4, 0x52, 0x33, 0x8E, 0x1F, 0xFD,
132 0x9A, 0x1B, 0xE9, 0x49, 0x8F, 0x81, 0x3D, 0x76,
133 0x53, 0x34, 0x49, 0xB6, 0x77, 0x8D, 0xCA, 0xD8,
134 0xC7, 0x8A, 0x8D, 0x2B, 0xA9, 0xAC, 0x66, 0x08,
135 0x5D, 0x0E, 0x53, 0xD5, 0x9C, 0x26, 0xC2, 0xD1,
136 0xC4, 0x90, 0xC1, 0xEB, 0xBE, 0x0C, 0xE6, 0x6D,
137 0x1B, 0x6B, 0x1B, 0x13, 0xB6, 0xB9, 0x19, 0xB8,
138 0x47, 0xC2, 0x5A, 0x91, 0x44, 0x7A, 0x95, 0xE7,
139 0x5E, 0x4E, 0xF1, 0x67, 0x79, 0xCD, 0xE8, 0xBF,
140 0x0A, 0x95, 0x85, 0x0E, 0x32, 0xAF, 0x96, 0x89,
141 0x44, 0x4F, 0xD3, 0x77, 0x10, 0x8F, 0x98, 0xFD,
142 0xCB, 0xD4, 0xE7, 0x26, 0x56, 0x75, 0x00, 0x99,
143 0x0B, 0xCC, 0x7E, 0x0C, 0xA3, 0xC4, 0xAA, 0xA3,
144 0x04, 0xA3, 0x87, 0xD2, 0x0F, 0x3B, 0x8F, 0xBB,
145 0xCD, 0x42, 0xA1, 0xBD, 0x31, 0x1D, 0x7A, 0x43,
146 0x03, 0xDD, 0xA5, 0xAB, 0x07, 0x88, 0x96, 0xAE,
147 0x80, 0xC1, 0x8B, 0x0A, 0xF6, 0x6D, 0xFF, 0x31,
148 0x96, 0x16, 0xEB, 0x78, 0x4E, 0x49, 0x5A, 0xD2,
149 0xCE, 0x90, 0xD7, 0xF7, 0x72, 0xA8, 0x17, 0x47,
150 0xB6, 0x5F, 0x62, 0x09, 0x3B, 0x1E, 0x0D, 0xB9,
151 0xE5, 0xBA, 0x53, 0x2F, 0xAF, 0xEC, 0x47, 0x50,
152 0x83, 0x23, 0xE6, 0x71, 0x32, 0x7D, 0xF9, 0x44,
153 0x44, 0x32, 0xCB, 0x73, 0x67, 0xCE, 0xC8, 0x2F,
154 0x5D, 0x44, 0xC0, 0xD0, 0x0B, 0x67, 0xD6, 0x50,
155 0xA0, 0x75, 0xCD, 0x4B, 0x70, 0xDE, 0xDD, 0x77,
156 0xEB, 0x9B, 0x10, 0x23, 0x1B, 0x6B, 0x5B, 0x74,
157 0x13, 0x47, 0x39, 0x6D, 0x62, 0x89, 0x74, 0x21,
158 0xD4, 0x3D, 0xF9, 0xB4, 0x2E, 0x44, 0x6E, 0x35,
159 0x8E, 0x9C, 0x11, 0xA9, 0xB2, 0x18, 0x4E, 0xCB,
160 0xEF, 0x0C, 0xD8, 0xE7, 0xA8, 0x77, 0xEF, 0x96,
161 0x8F, 0x13, 0x90, 0xEC, 0x9B, 0x3D, 0x35, 0xA5,
162 0x58, 0x5C, 0xB0, 0x09, 0x29, 0x0E, 0x2F, 0xCD,
163 0xE7, 0xB5, 0xEC, 0x66, 0xD9, 0x08, 0x4B, 0xE4,
164 0x40, 0x55, 0xA6, 0x19, 0xD9, 0xDD, 0x7F, 0xC3,
165 0x16, 0x6F, 0x94, 0x87, 0xF7, 0xCB, 0x27, 0x29,
166 0x12, 0x42, 0x64, 0x45, 0x99, 0x85, 0x14, 0xC1,
167 0x5D, 0x53, 0xA1, 0x8C, 0x86, 0x4C, 0xE3, 0xA2,
168 0xB7, 0x55, 0x57, 0x93, 0x98, 0x81, 0x26, 0x52,
169 0x0E, 0xAC, 0xF2, 0xE3, 0x06, 0x6E, 0x23, 0x0C,
170 0x91, 0xBE, 0xE4, 0xDD, 0x53, 0x04, 0xF5, 0xFD,
171 0x04, 0x05, 0xB3, 0x5B, 0xD9, 0x9C, 0x73, 0x13,
172 0x5D, 0x3D, 0x9B, 0xC3, 0x35, 0xEE, 0x04, 0x9E,
173 0xF6, 0x9B, 0x38, 0x67, 0xBF, 0x2D, 0x7B, 0xD1,
174 0xEA, 0xA5, 0x95, 0xD8, 0xBF, 0xC0, 0x06, 0x6F,
175 0xF8, 0xD3, 0x15, 0x09, 0xEB, 0x0C, 0x6C, 0xAA,
176 0x00, 0x6C, 0x80, 0x7A, 0x62, 0x3E, 0xF8, 0x4C,
177 0x3D, 0x33, 0xC1, 0x95, 0xD2, 0x3E, 0xE3, 0x20,
178 0xC4, 0x0D, 0xE0, 0x55, 0x81, 0x57, 0xC8, 0x22,
179 0xD4, 0xB8, 0xC5, 0x69, 0xD8, 0x49, 0xAE, 0xD5,
180 0x9D, 0x4E, 0x0F, 0xD7, 0xF3, 0x79, 0x58, 0x6B,
181 0x4B, 0x7F, 0xF6, 0x84, 0xED, 0x6A, 0x18, 0x9F,
182 0x74, 0x86, 0xD4, 0x9B, 0x9C, 0x4B, 0xAD, 0x9B,
183 0xA2, 0x4B, 0x96, 0xAB, 0xF9, 0x24, 0x37, 0x2C,
184 0x8A, 0x8F, 0xFF, 0xB1, 0x0D, 0x55, 0x35, 0x49,
185 0x00, 0xA7, 0x7A, 0x3D, 0xB5, 0xF2, 0x05, 0xE1,
186 0xB9, 0x9F, 0xCD, 0x86, 0x60, 0x86, 0x3A, 0x15,
187 0x9A, 0xD4, 0xAB, 0xE4, 0x0F, 0xA4, 0x89, 0x34,
188 0x16, 0x3D, 0xDD, 0xE5, 0x42, 0xA6, 0x58, 0x55,
189 0x40, 0xFD, 0x68, 0x3C, 0xBF, 0xD8, 0xC0, 0x0F,
190 0x12, 0x12, 0x9A, 0x28, 0x4D, 0xEA, 0xCC, 0x4C,
191 0xDE, 0xFE, 0x58, 0xBE, 0x71, 0x37, 0x54, 0x1C,
192 0x04, 0x71, 0x26, 0xC8, 0xD4, 0x9E, 0x27, 0x55,
193 0xAB, 0x18, 0x1A, 0xB7, 0xE9, 0x40, 0xB0, 0xC0 };
194
195 /* Test vector from the State/Commerce Department */
196
197 static const BYTE FAR_BSS testRC4key6[] =
198 { 0x61, 0x8A, 0x63, 0xD2, 0xFB };
199 static const BYTE FAR_BSS testRC4plaintext6[] =
200 { 0xDC, 0xEE, 0x4C, 0xF9, 0x2C };
201 static const BYTE FAR_BSS testRC4ciphertext6[] =
202 { 0xF1, 0x38, 0x29, 0xC9, 0xDE };
203
204 /* Test the RC4 code against the test vectors from the BSAFE implementation */
205
rc4Test(const BYTE * key,const int keySize,const BYTE * plaintext,const BYTE * ciphertext,const int length)206 static int rc4Test( const BYTE *key, const int keySize,
207 const BYTE *plaintext, const BYTE *ciphertext,
208 const int length )
209 {
210 const CAPABILITY_INFO *capabilityInfo = getRC4Capability();
211 CONTEXT_INFO contextInfo;
212 CONV_INFO contextData;
213 BYTE keyData[ RC4_EXPANDED_KEYSIZE + 8 ];
214 BYTE temp[ 512 + 8 ];
215 int status;
216
217 staticInitContext( &contextInfo, CONTEXT_CONV, capabilityInfo,
218 &contextData, sizeof( CONV_INFO ), keyData );
219 memcpy( temp, plaintext, length );
220 status = capabilityInfo->initKeyFunction( &contextInfo, key, keySize );
221 if( cryptStatusOK( status ) )
222 status = capabilityInfo->encryptCFBFunction( &contextInfo, temp,
223 length );
224 staticDestroyContext( &contextInfo );
225 if( cryptStatusError( status ) || \
226 memcmp( ciphertext, temp, length ) )
227 return( CRYPT_ERROR_FAILED );
228
229 return( CRYPT_OK );
230 }
231
selfTest(void)232 static int selfTest( void )
233 {
234 /* We can't use the standard testCipher() for this test because of the
235 variable-length arrays, so we have to perform the tests manually */
236 if( rc4Test( testRC4key1, sizeof( testRC4key1 ), testRC4plaintext1,
237 testRC4ciphertext1, sizeof( testRC4plaintext1 ) ) != CRYPT_OK ||
238 rc4Test( testRC4key2, sizeof( testRC4key2 ), testRC4plaintext2,
239 testRC4ciphertext2, sizeof( testRC4plaintext2 ) ) != CRYPT_OK ||
240 rc4Test( testRC4key3, sizeof( testRC4key3 ), testRC4plaintext3,
241 testRC4ciphertext3, sizeof( testRC4plaintext3 ) ) != CRYPT_OK ||
242 rc4Test( testRC4key4, sizeof( testRC4key4 ), testRC4plaintext4,
243 testRC4ciphertext4, sizeof( testRC4plaintext4 ) ) != CRYPT_OK ||
244 rc4Test( testRC4key5, sizeof( testRC4key5 ), testRC4plaintext5,
245 testRC4ciphertext5, sizeof( testRC4plaintext5 ) ) != CRYPT_OK ||
246 rc4Test( testRC4key6, sizeof( testRC4key6 ), testRC4plaintext6,
247 testRC4ciphertext6, sizeof( testRC4plaintext6 ) ) != CRYPT_OK )
248 return( CRYPT_ERROR_FAILED );
249
250 return( CRYPT_OK );
251 }
252 #else
253 #define selfTest NULL
254 #endif /* !CONFIG_NO_SELFTEST */
255
256 /****************************************************************************
257 * *
258 * Control Routines *
259 * *
260 ****************************************************************************/
261
262 /* Return context subtype-specific information */
263
264 CHECK_RETVAL STDC_NONNULL_ARG( ( 3 ) ) \
getInfo(IN_ENUM (CAPABILITY_INFO)const CAPABILITY_INFO_TYPE type,INOUT_OPT CONTEXT_INFO * contextInfoPtr,OUT void * data,IN_INT_Z const int length)265 static int getInfo( IN_ENUM( CAPABILITY_INFO ) const CAPABILITY_INFO_TYPE type,
266 INOUT_OPT CONTEXT_INFO *contextInfoPtr,
267 OUT void *data,
268 IN_INT_Z const int length )
269 {
270 assert( contextInfoPtr == NULL || \
271 isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );
272 assert( ( length == 0 && isWritePtr( data, sizeof( int ) ) ) || \
273 ( length > 0 && isWritePtr( data, length ) ) );
274
275 REQUIRES( type > CAPABILITY_INFO_NONE && type < CAPABILITY_INFO_LAST );
276
277 if( type == CAPABILITY_INFO_STATESIZE )
278 {
279 int *valuePtr = ( int * ) data;
280
281 *valuePtr = RC4_EXPANDED_KEYSIZE;
282
283 return( CRYPT_OK );
284 }
285
286 return( getDefaultInfo( type, contextInfoPtr, data, length ) );
287 }
288
289 /****************************************************************************
290 * *
291 * RC4 En/Decryption Routines *
292 * *
293 ****************************************************************************/
294
295 /* Encrypt/decrypt data. Since RC4 is a stream cipher, encryption and
296 decryption are the same operation. We have to append the distinguisher
297 'Fn' to the name since some systems already have 'encrypt' and 'decrypt'
298 in their standard headers */
299
encryptFn(CONTEXT_INFO * contextInfoPtr,BYTE * buffer,int noBytes)300 static int encryptFn( CONTEXT_INFO *contextInfoPtr, BYTE *buffer,
301 int noBytes )
302 {
303 CONV_INFO *convInfo = contextInfoPtr->ctxConv;
304
305 RC4( ( RC4_KEY * ) convInfo->key, noBytes, buffer, buffer );
306
307 return( CRYPT_OK );
308 }
309
310 /****************************************************************************
311 * *
312 * RC4 Key Management Routines *
313 * *
314 ****************************************************************************/
315
316 /* Create an expanded RC4 key */
317
initKey(CONTEXT_INFO * contextInfoPtr,const void * key,const int keyLength)318 static int initKey( CONTEXT_INFO *contextInfoPtr, const void *key,
319 const int keyLength )
320 {
321 CONV_INFO *convInfo = contextInfoPtr->ctxConv;
322
323 /* Copy the key to internal storage */
324 if( convInfo->userKey != key )
325 memcpy( convInfo->userKey, key, keyLength );
326 convInfo->userKeyLength = keyLength;
327
328 RC4_set_key( ( RC4_KEY * ) convInfo->key, keyLength, ( BYTE * ) key );
329 return( CRYPT_OK );
330 }
331
332 /****************************************************************************
333 * *
334 * Capability Access Routines *
335 * *
336 ****************************************************************************/
337
338 static const CAPABILITY_INFO FAR_BSS capabilityInfo = {
339 CRYPT_ALGO_RC4, bitsToBytes( 8 ), "RC4", 3,
340 MIN_KEYSIZE, bitsToBytes( 128 ), 256,
341 selfTest, getInfo, NULL, initGenericParams, initKey, NULL,
342 NULL, NULL, NULL, NULL, encryptFn, encryptFn
343 };
344
getRC4Capability(void)345 const CAPABILITY_INFO *getRC4Capability( void )
346 {
347 return( &capabilityInfo );
348 }
349
350 #endif /* USE_RC4 */
351