cryptlib  3.4.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Macros
ctx_des.c
Go to the documentation of this file.
1 /****************************************************************************
2 * *
3 * cryptlib DES Encryption Routines *
4 * Copyright Peter Gutmann 1995-2005 *
5 * *
6 ****************************************************************************/
7 
8 #if defined( INC_ALL )
9  #include "crypt.h"
10  #include "context.h"
11  #include "des.h"
12 #else
13  #include "crypt.h"
14  #include "context/context.h"
15  #include "crypt/des.h"
16 #endif /* Compiler-specific includes */
17 
18 /* The DES block size */
19 
20 #define DES_BLOCKSIZE 8
21 
22 #if defined( INC_ALL )
23  #include "testdes.h"
24 #else
25  #include "crypt/testdes.h"
26 #endif /* Compiler-specific includes */
27 
28 /* The scheduled DES key and size of the keyscheduled DES key */
29 
30 #define DES_KEY Key_schedule
31 #define DES_KEYSIZE sizeof( Key_schedule )
32 
33 /****************************************************************************
34 * *
35 * DES Self-test Routines *
36 * *
37 ****************************************************************************/
38 
39 #ifndef CONFIG_NO_SELFTEST
40 
41 /* Test the DES implementation against the test vectors given in NBS Special
42  Publication 500-20, 1980 */
43 
44 static int testLoop( const DES_TEST *testDES, int iterations, BOOLEAN isEncrypt )
45  {
46  const CAPABILITY_INFO *capabilityInfo = getDESCapability();
47  BYTE keyData[ DES_KEYSIZE + 8 ];
48  int i, status;
49 
50  for( i = 0; i < iterations; i++ )
51  {
52  /* The self-test uses weak keys, which means they'll be rejected by
53  the key-load function if it checks for these. For the OpenSSL
54  DES implementation we can kludge around this by temporarily
55  clearing the global des_check_key value, but for other
56  implementations some alternative workaround will be necessary */
58  status = testCipher( capabilityInfo, keyData, testDES[ i ].key,
59  DES_BLOCKSIZE, testDES[ i ].plaintext,
60  testDES[ i ].ciphertext );
62  if( cryptStatusError( status ) )
63  return( status );
64  }
65 
66  return( CRYPT_OK );
67  }
68 
69 static int selfTest( void )
70  {
71  /* Check the DES test vectors. Note that we don't explicitly test
72  the RS values, however these are tested implicitly since they're
73  just the decrypt side of the KP tests */
74  if( ( testLoop( testIP, sizeof( testIP ) / sizeof( DES_TEST ),
75  TRUE ) != CRYPT_OK ) || \
76  ( testLoop( testVP, sizeof( testVP ) / sizeof( DES_TEST ),
77  TRUE ) != CRYPT_OK ) || \
78  ( testLoop( testKP, sizeof( testKP ) / sizeof( DES_TEST ),
79  TRUE ) != CRYPT_OK ) || \
80  ( testLoop( testDP, sizeof( testDP ) / sizeof( DES_TEST ),
81  TRUE ) != CRYPT_OK ) || \
82  ( testLoop( testSB, sizeof( testSB ) / sizeof( DES_TEST ),
83  TRUE ) != CRYPT_OK ) )
84  return( CRYPT_ERROR_FAILED );
85 
86  return( CRYPT_OK );
87  }
88 #else
89  #define selfTest NULL
90 #endif /* !CONFIG_NO_SELFTEST */
91 
92 /****************************************************************************
93 * *
94 * Control Routines *
95 * *
96 ****************************************************************************/
97 
98 /* Return context subtype-specific information */
99 
101 static int getInfo( IN_ENUM( CAPABILITY_INFO ) const CAPABILITY_INFO_TYPE type,
103  OUT void *data,
104  IN_INT_Z const int length )
105  {
106  assert( contextInfoPtr == NULL || \
107  isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );
108  assert( ( length == 0 && isWritePtr( data, sizeof( int ) ) ) || \
109  ( length > 0 && isWritePtr( data, length ) ) );
110 
112 
113  if( type == CAPABILITY_INFO_STATESIZE )
114  {
115  int *valuePtr = ( int * ) data;
116 
117  *valuePtr = DES_KEYSIZE;
118 
119  return( CRYPT_OK );
120  }
121 
122  return( getDefaultInfo( type, contextInfoPtr, data, length ) );
123  }
124 
125 /****************************************************************************
126 * *
127 * DES En/Decryption Routines *
128 * *
129 ****************************************************************************/
130 
131 /* Encrypt/decrypt data in ECB mode */
132 
133 static int encryptECB( CONTEXT_INFO *contextInfoPtr, BYTE *buffer,
134  int noBytes )
135  {
136  CONV_INFO *convInfo = contextInfoPtr->ctxConv;
137  int blockCount = noBytes / DES_BLOCKSIZE;
138 
139  while( blockCount-- > 0 )
140  {
141  /* Encrypt a block of data */
142  des_ecb_encrypt( ( C_Block * ) buffer, ( C_Block * ) buffer,
143  *( DES_KEY * ) convInfo->key, DES_ENCRYPT );
144 
145  /* Move on to next block of data */
146  buffer += DES_BLOCKSIZE;
147  }
148 
149  return( CRYPT_OK );
150  }
151 
152 static int decryptECB( CONTEXT_INFO *contextInfoPtr, BYTE *buffer,
153  int noBytes )
154  {
155  CONV_INFO *convInfo = contextInfoPtr->ctxConv;
156  int blockCount = noBytes / DES_BLOCKSIZE;
157 
158  while( blockCount-- > 0 )
159  {
160  /* Decrypt a block of data */
161  des_ecb_encrypt( ( C_Block * ) buffer, ( C_Block * ) buffer,
162  *( DES_KEY * ) convInfo->key, DES_DECRYPT );
163 
164  /* Move on to next block of data */
165  buffer += DES_BLOCKSIZE;
166  }
167 
168  return( CRYPT_OK );
169  }
170 
171 /* Encrypt/decrypt data in CBC mode */
172 
173 static int encryptCBC( CONTEXT_INFO *contextInfoPtr, BYTE *buffer,
174  int noBytes )
175  {
176  CONV_INFO *convInfo = contextInfoPtr->ctxConv;
177 
178  des_ncbc_encrypt( buffer, buffer, noBytes, *( DES_KEY * ) convInfo->key,
179  ( C_Block * ) convInfo->currentIV, DES_ENCRYPT );
180 
181  return( CRYPT_OK );
182  }
183 
184 static int decryptCBC( CONTEXT_INFO *contextInfoPtr, BYTE *buffer,
185  int noBytes )
186  {
187  CONV_INFO *convInfo = contextInfoPtr->ctxConv;
188 
189  des_ncbc_encrypt( buffer, buffer, noBytes, *( DES_KEY * ) convInfo->key,
190  ( C_Block * ) convInfo->currentIV, DES_DECRYPT );
191 
192  return( CRYPT_OK );
193  }
194 
195 /* Encrypt/decrypt data in CFB mode */
196 
197 static int encryptCFB( CONTEXT_INFO *contextInfoPtr, BYTE *buffer,
198  int noBytes )
199  {
200  CONV_INFO *convInfo = contextInfoPtr->ctxConv;
201  int i, ivCount = convInfo->ivCount;
202 
203  /* If there's any encrypted material left in the IV, use it now */
204  if( ivCount > 0 )
205  {
206  int bytesToUse;
207 
208  /* Find out how much material left in the encrypted IV we can use */
209  bytesToUse = DES_BLOCKSIZE - ivCount;
210  if( noBytes < bytesToUse )
211  bytesToUse = noBytes;
212 
213  /* Encrypt the data */
214  for( i = 0; i < bytesToUse; i++ )
215  buffer[ i ] ^= convInfo->currentIV[ i + ivCount ];
216  memcpy( convInfo->currentIV + ivCount, buffer, bytesToUse );
217 
218  /* Adjust the byte count and buffer position */
219  noBytes -= bytesToUse;
220  buffer += bytesToUse;
221  ivCount += bytesToUse;
222  }
223 
224  while( noBytes > 0 )
225  {
226  ivCount = ( noBytes > DES_BLOCKSIZE ) ? DES_BLOCKSIZE : noBytes;
227 
228  /* Encrypt the IV */
229  des_ecb_encrypt( ( C_Block * ) convInfo->currentIV,
230  ( C_Block * ) convInfo->currentIV,
231  *( DES_KEY * ) convInfo->key, DES_ENCRYPT );
232 
233  /* XOR the buffer contents with the encrypted IV */
234  for( i = 0; i < ivCount; i++ )
235  buffer[ i ] ^= convInfo->currentIV[ i ];
236 
237  /* Shift the ciphertext into the IV */
238  memcpy( convInfo->currentIV, buffer, ivCount );
239 
240  /* Move on to next block of data */
241  noBytes -= ivCount;
242  buffer += ivCount;
243  }
244 
245  /* Remember how much of the IV is still available for use */
246  convInfo->ivCount = ( ivCount % DES_BLOCKSIZE );
247 
248  return( CRYPT_OK );
249  }
250 
251 static int decryptCFB( CONTEXT_INFO *contextInfoPtr, BYTE *buffer,
252  int noBytes )
253  {
254  CONV_INFO *convInfo = contextInfoPtr->ctxConv;
255  BYTE temp[ DES_BLOCKSIZE + 8 ];
256  int i, ivCount = convInfo->ivCount;
257 
258  /* If there's any encrypted material left in the IV, use it now */
259  if( ivCount > 0 )
260  {
261  int bytesToUse;
262 
263  /* Find out how much material left in the encrypted IV we can use */
264  bytesToUse = DES_BLOCKSIZE - ivCount;
265  if( noBytes < bytesToUse )
266  bytesToUse = noBytes;
267 
268  /* Decrypt the data */
269  memcpy( temp, buffer, bytesToUse );
270  for( i = 0; i < bytesToUse; i++ )
271  buffer[ i ] ^= convInfo->currentIV[ i + ivCount ];
272  memcpy( convInfo->currentIV + ivCount, temp, bytesToUse );
273 
274  /* Adjust the byte count and buffer position */
275  noBytes -= bytesToUse;
276  buffer += bytesToUse;
277  ivCount += bytesToUse;
278  }
279 
280  while( noBytes > 0 )
281  {
282  ivCount = ( noBytes > DES_BLOCKSIZE ) ? DES_BLOCKSIZE : noBytes;
283 
284  /* Encrypt the IV */
285  des_ecb_encrypt( ( C_Block * ) convInfo->currentIV,
286  ( C_Block * ) convInfo->currentIV,
287  *( DES_KEY * ) convInfo->key, DES_ENCRYPT );
288 
289  /* Save the ciphertext */
290  memcpy( temp, buffer, ivCount );
291 
292  /* XOR the buffer contents with the encrypted IV */
293  for( i = 0; i < ivCount; i++ )
294  buffer[ i ] ^= convInfo->currentIV[ i ];
295 
296  /* Shift the ciphertext into the IV */
297  memcpy( convInfo->currentIV, temp, ivCount );
298 
299  /* Move on to next block of data */
300  noBytes -= ivCount;
301  buffer += ivCount;
302  }
303 
304  /* Remember how much of the IV is still available for use */
305  convInfo->ivCount = ( ivCount % DES_BLOCKSIZE );
306 
307  /* Clear the temporary buffer */
308  zeroise( temp, DES_BLOCKSIZE );
309 
310  return( CRYPT_OK );
311  }
312 
313 /* Encrypt/decrypt data in OFB mode */
314 
315 static int encryptOFB( CONTEXT_INFO *contextInfoPtr, BYTE *buffer,
316  int noBytes )
317  {
318  CONV_INFO *convInfo = contextInfoPtr->ctxConv;
319  int i, ivCount = convInfo->ivCount;
320 
321  /* If there's any encrypted material left in the IV, use it now */
322  if( ivCount > 0 )
323  {
324  int bytesToUse;
325 
326  /* Find out how much material left in the encrypted IV we can use */
327  bytesToUse = DES_BLOCKSIZE - ivCount;
328  if( noBytes < bytesToUse )
329  bytesToUse = noBytes;
330 
331  /* Encrypt the data */
332  for( i = 0; i < bytesToUse; i++ )
333  buffer[ i ] ^= convInfo->currentIV[ i + ivCount ];
334 
335  /* Adjust the byte count and buffer position */
336  noBytes -= bytesToUse;
337  buffer += bytesToUse;
338  ivCount += bytesToUse;
339  }
340 
341  while( noBytes > 0 )
342  {
343  ivCount = ( noBytes > DES_BLOCKSIZE ) ? DES_BLOCKSIZE : noBytes;
344 
345  /* Encrypt the IV */
346  des_ecb_encrypt( ( C_Block * ) convInfo->currentIV,
347  ( C_Block * ) convInfo->currentIV,
348  *( DES_KEY * ) convInfo->key, DES_ENCRYPT );
349 
350  /* XOR the buffer contents with the encrypted IV */
351  for( i = 0; i < ivCount; i++ )
352  buffer[ i ] ^= convInfo->currentIV[ i ];
353 
354  /* Move on to next block of data */
355  noBytes -= ivCount;
356  buffer += ivCount;
357  }
358 
359  /* Remember how much of the IV is still available for use */
360  convInfo->ivCount = ( ivCount % DES_BLOCKSIZE );
361 
362  return( CRYPT_OK );
363  }
364 
365 static int decryptOFB( CONTEXT_INFO *contextInfoPtr, BYTE *buffer,
366  int noBytes )
367  {
368  CONV_INFO *convInfo = contextInfoPtr->ctxConv;
369  int i, ivCount = convInfo->ivCount;
370 
371  /* If there's any encrypted material left in the IV, use it now */
372  if( ivCount > 0 )
373  {
374  int bytesToUse;
375 
376  /* Find out how much material left in the encrypted IV we can use */
377  bytesToUse = DES_BLOCKSIZE - ivCount;
378  if( noBytes < bytesToUse )
379  bytesToUse = noBytes;
380 
381  /* Decrypt the data */
382  for( i = 0; i < bytesToUse; i++ )
383  buffer[ i ] ^= convInfo->currentIV[ i + ivCount ];
384 
385  /* Adjust the byte count and buffer position */
386  noBytes -= bytesToUse;
387  buffer += bytesToUse;
388  ivCount += bytesToUse;
389  }
390 
391  while( noBytes > 0 )
392  {
393  ivCount = ( noBytes > DES_BLOCKSIZE ) ? DES_BLOCKSIZE : noBytes;
394 
395  /* Encrypt the IV */
396  des_ecb_encrypt( ( C_Block * ) convInfo->currentIV,
397  ( C_Block * ) convInfo->currentIV,
398  *( DES_KEY * ) convInfo->key, DES_ENCRYPT );
399 
400  /* XOR the buffer contents with the encrypted IV */
401  for( i = 0; i < ivCount; i++ )
402  buffer[ i ] ^= convInfo->currentIV[ i ];
403 
404  /* Move on to next block of data */
405  noBytes -= ivCount;
406  buffer += ivCount;
407  }
408 
409  /* Remember how much of the IV is still available for use */
410  convInfo->ivCount = ( ivCount % DES_BLOCKSIZE );
411 
412  return( CRYPT_OK );
413  }
414 
415 /****************************************************************************
416 * *
417 * DES Key Management Routines *
418 * *
419 ****************************************************************************/
420 
421 /* Key schedule a DES key */
422 
423 static int initKey( CONTEXT_INFO *contextInfoPtr, const void *key,
424  const int keyLength )
425  {
426  CONV_INFO *convInfo = contextInfoPtr->ctxConv;
427 
428  /* Copy the key to internal storage */
429  if( convInfo->userKey != key )
430  memcpy( convInfo->userKey, key, keyLength );
431  convInfo->userKeyLength = keyLength;
432 
433  /* Call the libdes key schedule code. Returns with -1 if the key parity
434  is wrong (which never occurs since we force the correct parity) or -2
435  if a weak key is used. In theory this could leave us open to timing
436  attacks (a memcmp() implemented as a bytewise operation will exit on
437  the first mis-matching byte), but in practice the trip through the
438  kernel adds enough skew to make the one or two clock cycle difference
439  undetectable */
440  des_set_odd_parity( ( C_Block * ) convInfo->userKey );
441  if( des_key_sched( ( C_Block * ) convInfo->userKey,
442  *( DES_KEY * ) convInfo->key ) )
443  return( CRYPT_ARGERROR_STR1 );
444 
445  return( CRYPT_OK );
446  }
447 
448 /****************************************************************************
449 * *
450 * Capability Access Routines *
451 * *
452 ****************************************************************************/
453 
454 static const CAPABILITY_INFO FAR_BSS capabilityInfo = {
455  CRYPT_ALGO_DES, bitsToBytes( 64 ), "DES", 3,
456  MIN_KEYSIZE, bitsToBytes( 64 ), bitsToBytes( 64 ),
457  selfTest, getInfo, NULL, initGenericParams, initKey, NULL,
458  encryptECB, decryptECB, encryptCBC, decryptCBC,
459  encryptCFB, decryptCFB, encryptOFB, decryptOFB
460  };
461 
463  {
464  return( &capabilityInfo );
465  }