cryptlib  3.4.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Macros
ctx_rc4.c
Go to the documentation of this file.
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 
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->encryptOFBFunction( &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 
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 
265 static int getInfo( IN_ENUM( CAPABILITY_INFO ) const CAPABILITY_INFO_TYPE type,
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 
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 
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 
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, NULL, NULL, encryptFn, encryptFn
343  };
344 
345 const CAPABILITY_INFO *getRC4Capability( void )
346  {
347  return( &capabilityInfo );
348  }
349 
350 #endif /* USE_RC4 */