cryptlib  3.4.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Macros
lowlvl.c
Go to the documentation of this file.
1 /****************************************************************************
2 * *
3 * cryptlib Low-level Test Routines *
4 * Copyright Peter Gutmann 1995-2004 *
5 * *
6 ****************************************************************************/
7 
8 #include "cryptlib.h"
9 #include "test/test.h"
10 
11 #if defined( __MVS__ ) || defined( __VMCMS__ )
12  /* Suspend conversion of literals to ASCII. */
13  #pragma convlit( suspend )
14 #endif /* IBM big iron */
15 #if defined( __ILEC400__ )
16  #pragma convert( 0 )
17 #endif /* IBM medium iron */
18 
19 /* The size of the test buffers */
20 
21 #define TESTBUFFER_SIZE 256
22 
23 /* Since the DH/ECDH operations aren't visible externally, we have to use
24  the kernel API to perform the test. To get the necessary definitions
25  and prototypes, we have to use crypt.h, however since we've already
26  included cryptlib.h the built-in guards preclude us from pulling it in
27  again with the internal-only values defined, so we have to explicitly
28  define things like attribute values that normally aren't visible
29  externally */
30 
31 #ifdef TEST_DH
32  #undef __WINDOWS__
33  #undef __WIN16__
34  #undef __WIN32__
35  #undef BYTE
36  #include "crypt.h"
37 #endif /* TEST_DH */
38 
39 #if defined( TEST_LOWLEVEL ) || defined( TEST_KEYSET ) /* Needed for PGP keysets */
40 
41 /****************************************************************************
42 * *
43 * Utility Functions *
44 * *
45 ****************************************************************************/
46 
47 /* Check for an algorithm/mode */
48 
49 static BOOLEAN checkLowlevelInfo( const CRYPT_DEVICE cryptDevice,
51  {
52  CRYPT_QUERY_INFO cryptQueryInfo;
53  const BOOLEAN isDevice = ( cryptDevice != CRYPT_UNUSED ) ? TRUE : FALSE;
54  int status;
55 
56  if( isDevice )
57  status = cryptDeviceQueryCapability( cryptDevice, cryptAlgo,
58  &cryptQueryInfo );
59  else
60  status = cryptQueryCapability( cryptAlgo, &cryptQueryInfo );
61  if( cryptStatusError( status ) )
62  {
63  printf( "crypt%sQueryCapability() reports algorithm %d is not "
64  "available, status = %d.\n", isDevice ? "Device" : "",
65  cryptAlgo, status );
66  return( FALSE );
67  }
68 #ifdef UNICODE_STRINGS
69  printf( "cryptQueryCapability() reports availability of %S algorithm "
70  "with\n block size %d bits", cryptQueryInfo.algoName,
71  cryptQueryInfo.blockSize << 3 );
72 #else
73  printf( "cryptQueryCapability() reports availability of %s algorithm "
74  "with\n block size %d bits", cryptQueryInfo.algoName,
75  cryptQueryInfo.blockSize << 3 );
76 #endif /* UNICODE_STRINGS */
77  if( cryptAlgo < CRYPT_ALGO_FIRST_HASH || cryptAlgo > CRYPT_ALGO_LAST_HASH )
78  {
79  printf( ", keysize %d-%d bits (recommended = %d bits)",
80  cryptQueryInfo.minKeySize << 3,
81  cryptQueryInfo.maxKeySize << 3, cryptQueryInfo.keySize << 3 );
82  }
83  puts( "." );
84 
85  return( TRUE );
86  }
87 
88 /* Set a pair of encrypt/decrypt buffers to a known state, and make sure
89  that they're still in that known state */
90 
91 static void initTestBuffers( BYTE *buffer1, BYTE *buffer2, const int length )
92  {
93 #if defined( __MVS__ ) || defined( __VMCMS__ )
94  #pragma convlit( resume )
95 #endif /* IBM big iron */
96 #if defined( __ILEC400__ )
97  #pragma convert( 819 )
98 #endif /* IBM medium iron */
99  /* Set the buffers to a known state */
100  memset( buffer1, '*', length );
101  memcpy( buffer1, "12345678", 8 ); /* For endianness check */
102  if( buffer2 != NULL )
103  memcpy( buffer2, buffer1, length );
104 #if defined( __MVS__ ) || defined( __VMCMS__ )
105  #pragma convlit( suspend )
106 #endif /* IBM big iron */
107 #if defined( __ILEC400__ )
108  #pragma convert( 0 )
109 #endif /* IBM medium iron */
110  }
111 
112 static BOOLEAN checkTestBuffers( const BYTE *buffer1, const BYTE *buffer2 )
113  {
114  /* Make sure that everything went OK */
115  if( !memcmp( buffer1, buffer2, TESTBUFFER_SIZE ) )
116  return( TRUE );
117  puts( "Error: Decrypted data != original plaintext." );
118 
119  /* Try and guess at block chaining problems */
120  if( !memcmp( buffer1, "12345678****", 12 ) )
121  {
122  puts( "\t\bIt looks like there's a problem with block chaining." );
123  return( FALSE );
124  }
125 
126  /* Try and guess at endianness problems - we want "1234" */
127  if( !memcmp( buffer1, "4321", 4 ) )
128  {
129  puts( "\t\bIt looks like the 32-bit word endianness is reversed." );
130  return( FALSE );
131  }
132  if( !memcmp( buffer1, "2143", 4 ) )
133  {
134  puts( "\t\bIt looks like the 16-bit word endianness is reversed." );
135  return( FALSE );
136  }
137  if( buffer1[ 0 ] >= '1' && buffer1[ 0 ] <= '9' )
138  {
139  puts( "\t\bIt looks like there's some sort of endianness problem "
140  "which is\n\t more complex than just a reversal." );
141  return( FALSE );
142  }
143  puts( "\t\bIt's probably more than just an endianness problem." );
144  return( FALSE );
145  }
146 
147 /* Load the encryption contexts */
148 
149 static BOOLEAN loadContexts( CRYPT_CONTEXT *cryptContext, CRYPT_CONTEXT *decryptContext,
150  const CRYPT_DEVICE cryptDevice,
153  const BYTE *key, const int length )
154  {
155  const BOOLEAN isDevice = ( cryptDevice != CRYPT_UNUSED ) ? TRUE : FALSE;
156  const BOOLEAN hasKey = ( cryptAlgo >= CRYPT_ALGO_FIRST_CONVENTIONAL && \
157  cryptAlgo <= CRYPT_ALGO_LAST_CONVENTIONAL ) || \
158  ( cryptAlgo >= CRYPT_ALGO_FIRST_MAC && \
159  cryptAlgo <= CRYPT_ALGO_LAST_MAC );
160  BOOLEAN adjustKey = FALSE;
161  int status;
162 
163  /* Create the encryption context */
164  if( isDevice )
165  status = cryptDeviceCreateContext( cryptDevice, cryptContext,
166  cryptAlgo );
167  else
168  status = cryptCreateContext( cryptContext, CRYPT_UNUSED, cryptAlgo );
169  if( cryptStatusError( status ) )
170  {
171  printf( "crypt%sCreateContext() failed with error code %d, "
172  "line %d.\n", isDevice ? "Device" : "", status, __LINE__ );
173  return( FALSE );
174  }
175  if( cryptAlgo <= CRYPT_ALGO_LAST_CONVENTIONAL )
176  {
177  status = cryptSetAttribute( *cryptContext, CRYPT_CTXINFO_MODE,
178  cryptMode );
179  if( cryptStatusError( status ) )
180  {
181  cryptDestroyContext( *cryptContext );
182  if( status == CRYPT_ERROR_NOTAVAIL )
183  {
184  /* This mode isn't available, return a special-case value to
185  tell the calling code to continue */
186  return( status );
187  }
188  printf( "Encryption mode %d selection failed with status %d, "
189  "line %d.\n", cryptMode, status, __LINE__ );
190  return( FALSE );
191  }
192  }
193  if( hasKey )
194  {
195  status = cryptSetAttributeString( *cryptContext, CRYPT_CTXINFO_KEY,
196  key, length );
197  if( length > 16 && status == CRYPT_ERROR_PARAM4 )
198  {
199  status = cryptSetAttributeString( *cryptContext, CRYPT_CTXINFO_KEY,
200  key, 16 );
201  if( cryptStatusOK( status ) )
202  {
203  puts( " Load of full-length key failed, using shorter 128-"
204  "bit key." );
205  adjustKey = TRUE;
206  }
207  }
208  if( cryptStatusError( status ) )
209  {
210  printf( "Encryption key load failed with error code %d, "
211  "line %d.\n", status, __LINE__ );
212  return( FALSE );
213  }
214  }
215  if( decryptContext == NULL )
216  return( TRUE );
217 
218  /* Create the decryption context */
219  if( cryptDevice == CRYPT_UNUSED )
220  status = cryptCreateContext( decryptContext, CRYPT_UNUSED, cryptAlgo );
221  else
222  status = cryptDeviceCreateContext( cryptDevice, decryptContext,
223  cryptAlgo );
224  if( cryptStatusError( status ) )
225  {
226  printf( "crypt%sCreateContext() failed with error code %d, "
227  "line %d.\n", ( cryptDevice != CRYPT_UNUSED ) ? \
228  "Device" : "", status, __LINE__ );
229  return( FALSE );
230  }
231  if( cryptAlgo <= CRYPT_ALGO_LAST_CONVENTIONAL )
232  {
233  status = cryptSetAttribute( *decryptContext, CRYPT_CTXINFO_MODE,
234  cryptMode );
235  if( cryptStatusError( status ) )
236  {
237  cryptDestroyContext( *cryptContext );
238  if( status == CRYPT_ERROR_NOTAVAIL )
239  {
240  /* This mode isn't available, return a special-case value to
241  tell the calling code to continue */
242  return( status );
243  }
244  printf( "Encryption mode %d selection failed with status %d, "
245  "line %d.\n", cryptMode, status, __LINE__ );
246  return( FALSE );
247  }
248  }
249  if( hasKey )
250  {
251  status = cryptSetAttributeString( *decryptContext, CRYPT_CTXINFO_KEY,
252  key, adjustKey ? 16 : length );
253  if( cryptStatusError( status ) )
254  {
255  printf( "Decryption key load failed with error code %d, "
256  "line %d.\n", status, __LINE__ );
257  return( FALSE );
258  }
259  }
260 
261  return( TRUE );
262  }
263 
264 /* Perform a test en/decryption */
265 
266 int testCrypt( CRYPT_CONTEXT cryptContext, CRYPT_CONTEXT decryptContext,
267  BYTE *buffer, const BOOLEAN isDevice,
268  const BOOLEAN noWarnFail )
269  {
270  BYTE iv[ CRYPT_MAX_IVSIZE ];
271  BYTE localBuffer[ TESTBUFFER_SIZE ];
272  int cryptAlgo, cryptMode, status;
273 
274  /* If the user hasn't supplied a test buffer, use our own one */
275  if( buffer == NULL )
276  {
277  buffer = localBuffer;
278  initTestBuffers( buffer, NULL, TESTBUFFER_SIZE );
279  }
280 
281  /* Find out about the algorithm we're using */
282  cryptGetAttribute( cryptContext, CRYPT_CTXINFO_ALGO, &cryptAlgo );
283  cryptGetAttribute( cryptContext, CRYPT_CTXINFO_MODE, &cryptMode );
284  if( cryptAlgo <= CRYPT_ALGO_LAST_CONVENTIONAL && \
285  ( cryptMode == CRYPT_MODE_CFB || cryptMode == CRYPT_MODE_OFB ) )
286  {
287  /* Encrypt the buffer in two odd-sized chunks */
288  status = cryptEncrypt( cryptContext, buffer, 79 );
289  if( cryptStatusOK( status ) )
290  status = cryptEncrypt( cryptContext, buffer + 79,
291  TESTBUFFER_SIZE - 79 );
292  if( cryptStatusError( status ) )
293  {
294  printf( "Couldn't encrypt data, status = %d, line %d.\n",
295  status, __LINE__ );
296  return( status );
297  }
298 
299  /* Copy the IV from the encryption to the decryption context if
300  necessary */
301  if( cryptAlgo != CRYPT_ALGO_RC4 )
302  {
303  int ivLength;
304 
305  status = cryptGetAttributeString( cryptContext, CRYPT_CTXINFO_IV,
306  iv, &ivLength );
307  if( cryptStatusError( status ) )
308  {
309  printf( "Couldn't retrieve IV after encryption, status = %d, "
310  "line %d.\n", status, __LINE__ );
311  return( status );
312  }
313  status = cryptSetAttributeString( decryptContext, CRYPT_CTXINFO_IV,
314  iv, ivLength );
315  if( cryptStatusError( status ) )
316  {
317  printf( "Couldn't load IV for decryption, status = %d, "
318  "line %d.\n", status, __LINE__ );
319  return( status );
320  }
321  }
322 
323  /* Decrypt the buffer in different odd-size chunks */
324  status = cryptDecrypt( decryptContext, buffer, 125 );
325  if( cryptStatusOK( status ) )
326  status = cryptDecrypt( decryptContext, buffer + 125,
327  TESTBUFFER_SIZE - 125 );
328  if( cryptStatusError( status ) )
329  {
330  printf( "Couldn't decrypt data, status = %d, line %d.\n",
331  status, __LINE__ );
332  return( status );
333  }
334 
335  return( CRYPT_OK );
336  }
337  if( cryptAlgo <= CRYPT_ALGO_LAST_CONVENTIONAL && \
338  ( cryptMode == CRYPT_MODE_ECB || cryptMode == CRYPT_MODE_CBC || \
339  cryptMode == CRYPT_MODE_GCM ) )
340  {
341  /* Encrypt the buffer in two odd-sized chunks */
342  status = cryptEncrypt( cryptContext, buffer, 80 );
343  if( cryptStatusOK( status ) )
344  status = cryptEncrypt( cryptContext, buffer + 80,
345  TESTBUFFER_SIZE - 80 );
346  if( cryptStatusError( status ) )
347  {
348  printf( "Couldn't encrypt data, status = %d, line %d.\n",
349  status, __LINE__ );
350  return( status );
351  }
352 
353  /* Copy the IV from the encryption to the decryption context if
354  necessary */
355  if( cryptMode != CRYPT_MODE_ECB )
356  {
357  int ivLength;
358 
359  status = cryptGetAttributeString( cryptContext, CRYPT_CTXINFO_IV,
360  iv, &ivLength );
361  if( cryptStatusError( status ) )
362  printf( "Couldn't retrieve IV after encryption, status = %d, "
363  "line %d.\n", status, __LINE__ );
364  status = cryptSetAttributeString( decryptContext, CRYPT_CTXINFO_IV,
365  iv, ivLength );
366  if( cryptStatusError( status ) )
367  printf( "Couldn't load IV for decryption, status = %d, "
368  "line %d.\n", status, __LINE__ );
369  }
370 
371  /* Decrypt the buffer in different odd-size chunks */
372  status = cryptDecrypt( decryptContext, buffer, 128 );
373  if( cryptStatusOK( status ) )
374  status = cryptDecrypt( decryptContext, buffer + 128,
375  TESTBUFFER_SIZE - 128 );
376  if( cryptStatusError( status ) )
377  {
378  printf( "Couldn't decrypt data, status = %d, line %d.\n",
379  status, __LINE__ );
380  return( status );
381  }
382 
383  return( CRYPT_OK );
384  }
385 #ifdef TEST_DH
386  if( cryptAlgo == CRYPT_ALGO_DH || cryptAlgo == CRYPT_ALGO_ECDH )
387  {
388  KEYAGREE_PARAMS keyAgreeParams;
389  int status;
390 
391  /* Perform the DH/ECDH key agreement */
392  memset( &keyAgreeParams, 0, sizeof( KEYAGREE_PARAMS ) );
393 #if 0
394  status = krnlSendMessage( cryptContext, IMESSAGE_CTX_ENCRYPT,
395  &keyAgreeParams, sizeof( KEYAGREE_PARAMS ) );
396  if( cryptStatusOK( status ) )
397  status = krnlSendMessage( cryptContext, IMESSAGE_CTX_DECRYPT,
398  &keyAgreeParams, sizeof( KEYAGREE_PARAMS ) );
399 #else
400  status = cryptDeviceQueryCapability( cryptContext, 1001,
401  ( CRYPT_QUERY_INFO * ) &keyAgreeParams );
402  if( cryptStatusOK( status ) )
403  status = cryptDeviceQueryCapability( cryptContext, 1002,
404  ( CRYPT_QUERY_INFO * ) &keyAgreeParams );
405 #endif /* 0 */
406  if( cryptStatusError( status ) )
407  {
408  printf( "Couldn't perform DH/ECDH key agreement, status = %d, "
409  "line %d.\n", status, __LINE__ );
410  return( status );
411  }
412 
413  return( CRYPT_OK );
414  }
415 #endif /* TEST_DH */
416  if( cryptAlgo == CRYPT_ALGO_RSA )
417  {
418  static const BYTE FAR_BSS rsa512Value[] = \
419  "\x4E\x1F\x2F\x10\xA9\xFB\x4F\xD9\xC1\x25\x79\x7A\x36\x00\x58\xD0"
420  "\x9E\x8B\x9F\xBA\xC7\x04\x10\x77\xDB\xBC\xC9\xD1\x70\xCD\xF6\x86"
421  "\xA4\xDC\x39\xA9\x57\xD7\xC7\xE0\x87\xF2\x31\xDF\x83\x7d\x27\x0E"
422  "\xB4\xA6\x93\x3D\x11\xEB\xA5\x0E\x42\x66\x7B\x30\x50\x84\xC1\x81";
423  static const BYTE FAR_BSS rsa1024Value[] = \
424  "\x84\x8E\x00\x3E\x49\x11\x0D\x42\x4C\x71\x6B\xB4\xCF\x13\xDD\xCD"
425  "\x12\x30\x56\xC2\x4A\x55\x3B\xD8\x30\xA2\xB8\x73\xA7\xAB\xF0\x7A"
426  "\x2E\x07\x20\xCC\xBE\xEA\x58\x03\x56\xF6\x18\x27\x28\x4F\xE1\x02"
427  "\xC6\x49\x79\x6C\xB4\x7E\x6C\xC6\x93\x2E\xF1\x46\x83\x15\x5A\xB7"
428  "\x7D\xCC\x21\xEE\x4E\x3E\x0B\x8B\x85\xEE\x08\x21\xE6\xA7\x31\x53"
429  "\x2E\x92\x3D\x2D\xB0\xD4\xA1\x30\xF4\xE9\xEB\x37\xBF\xCD\x2F\xE1"
430  "\x60\x89\x19\xB6\x8C\x01\xFB\xD8\xAC\xF5\xC7\x4B\xB4\x74\x8A\x35"
431  "\x79\xE6\xE0\x48\xBD\x9C\x9F\xD7\x4A\x1C\x8A\x58\xAB\xA9\x3C\x44";
432  BYTE testBuffer[ TESTBUFFER_SIZE ], tmpBuffer[ 32 ];
433  BOOLEAN encryptOK = TRUE;
434  int length;
435 
436  /* Take a copy of the input so that we can compare it with the
437  decrypted output and find out how much data we need to process */
438  memcpy( testBuffer, buffer, TESTBUFFER_SIZE );
439  cryptGetAttribute( cryptContext, CRYPT_CTXINFO_KEYSIZE, &length );
440 
441  /* Since we're doing raw RSA encryption we need to format the data
442  specially to work with the RSA key being used. If we're using the
443  cryptlib native routines, we need to ensure that the magnitude of
444  the integer corresponding to the data to be encrypted is less than
445  the modulus, which we do by setting the first byte of the buffer
446  to 1. If we're using a crypto device, we need to create a (dummy)
447  PKCS #1-like format since some devices expect to see PKCS #1-
448  formatted data as input to/output from the RSA encryption/
449  decryption operation */
450  memcpy( tmpBuffer, buffer, 18 );
451  if( isDevice )
452  {
453  memcpy( buffer, "\x00\x02\xA5\xA5\xA5\xA5\xA5\xA5"
454  "\xA5\xA5\xA5\xA5\xA5\xA5\xA5\xA5"
455  "\xA5\x00", 18 );
456  }
457  else
458  buffer[ 0 ] = 1;
459 
460  /* Since the PKC algorithms only handle a single block, we only
461  perform a single encrypt and decrypt operation */
462  status = cryptEncrypt( cryptContext, buffer, length );
463  if( cryptStatusError( status ) )
464  {
465  if( !noWarnFail )
466  printf( "Couldn't encrypt data, status = %d, line %d.\n",
467  status, __LINE__ );
468  return( status );
469  }
470  if( cryptAlgo == CRYPT_ALGO_RSA && \
471  !isDevice && buffer != localBuffer && \
472  memcmp( buffer, ( length == 64 ) ? rsa512Value : rsa1024Value,
473  length ) )
474  {
475  /* For a non-randomized PKC the encryption of the fixed value
476  produces known output, so if we're being called from with a
477  fixed test key from testLowlevel() we make sure that this
478  matches the expected value. This makes diagnosing problems
479  rather easier */
480  puts( "The actual encrypted value doesn't match the expected value." );
481  encryptOK = FALSE;
482  }
483  status = cryptDecrypt( decryptContext, buffer, length );
484  if( cryptStatusError( status ) )
485  {
486  if( !noWarnFail )
487  {
488  if( encryptOK )
489  {
490  printf( "Couldn't decrypt data even though the "
491  "encrypted input data was valid,\nstatus = "
492  "%d, line %d.\n", status, __LINE__ );
493  }
494  else
495  {
496  printf( "Couldn't decrypt data, probably because the "
497  "data produced by the encrypt step\nwas "
498  "invalid, status = %d, line %d.\n", status,
499  __LINE__ );
500  }
501  }
502  return( status );
503  }
504  if( isDevice )
505  memcpy( buffer, tmpBuffer, 18 );
506  else
507  buffer[ 0 ] = tmpBuffer[ 0 ];
508 
509  /* Make sure that the recovered result matches the input data */
510  if( memcmp( buffer, testBuffer, length ) )
511  {
512  if( encryptOK )
513  {
514  /* This could happen with simple-minded CRT implementations
515  that only work when p > q (the test key has p < q in
516  order to find this problem) */
517  puts( "Decryption failed even though encryption produced "
518  "valid data. The RSA\ndecryption step is broken." );
519  }
520  else
521  {
522  puts( "Decryption failed because the encryption step "
523  "produced invalid data. The RSA\nencryption step is "
524  "broken." );
525  }
526  return( CRYPT_ERROR_FAILED );
527  }
528  else
529  if( !encryptOK )
530  {
531  puts( "Decryption succeeded even though encryption produced "
532  "invalid data. The RSA\nimplementation is broken." );
533  return( CRYPT_ERROR_FAILED );
534  }
535 
536  return( CRYPT_OK );
537  }
538  if( cryptAlgo >= CRYPT_ALGO_FIRST_HASH && \
539  cryptAlgo <= CRYPT_ALGO_LAST_MAC )
540  {
541  /* Hash the buffer in two odd-sized chunks. Note the use of the hash
542  wrap-up call, this is the only time when we can call
543  cryptEncrypt() with a zero length */
544  status = cryptEncrypt( cryptContext, buffer, 80 );
545  if( cryptStatusOK( status ) )
546  status = cryptEncrypt( cryptContext, buffer + 80,
547  TESTBUFFER_SIZE - 80 );
548  if( cryptStatusOK( status ) )
549  status = cryptEncrypt( cryptContext, buffer + TESTBUFFER_SIZE, 0 );
550  if( cryptStatusError( status ) )
551  {
552  printf( "Couldn't %s data, status = %d, line %d.\n",
553  ( cryptAlgo >= CRYPT_ALGO_FIRST_MAC ) ? "MAC" : "hash",
554  status, __LINE__ );
555  return( status );
556  }
557 
558  /* If we're just testing for the ability to use a context, the same
559  hash context may be used for both operations, in which case we
560  have to reset the context between the two */
561  if( cryptContext == decryptContext )
563 
564  /* Hash the buffer in different odd-size chunks */
565  status = cryptEncrypt( decryptContext, buffer, 128 );
566  if( cryptStatusOK( status ) )
567  status = cryptEncrypt( decryptContext, buffer + 128,
568  TESTBUFFER_SIZE - 128 );
569  if( cryptStatusOK( status ) )
570  status = cryptEncrypt( decryptContext, buffer + TESTBUFFER_SIZE, 0 );
571  if( cryptStatusError( status ) )
572  {
573  printf( "Couldn't %s data, status = %d, line %d.\n",
574  ( cryptAlgo >= CRYPT_ALGO_FIRST_MAC ) ? "MAC" : "hash",
575  status, __LINE__ );
576  return( status );
577  }
578 
579  return( CRYPT_OK );
580  }
581 
582  printf( "Unknown encryption algorithm/mode %d.\n", cryptAlgo );
583  return( CRYPT_OK );
584  }
585 
586 /****************************************************************************
587 * *
588 * Low-level Routines Test *
589 * *
590 ****************************************************************************/
591 
592 /* Test an algorithm/mode implementation */
593 
594 int testLowlevel( const CRYPT_DEVICE cryptDevice,
595  const CRYPT_ALGO_TYPE cryptAlgo, const BOOLEAN checkOnly )
596  {
597  CRYPT_MODE_TYPE cryptMode = CRYPT_MODE_ECB;
598  CRYPT_CONTEXT cryptContext, decryptContext;
599  BYTE buffer[ TESTBUFFER_SIZE ], testBuffer[ TESTBUFFER_SIZE ];
600  const BOOLEAN isDevice = ( cryptDevice != CRYPT_UNUSED ) ? TRUE : FALSE;
601  BOOLEAN modesTested[ 8 ] = { 0 }, testSucceeded = FALSE;
602  int status;
603 
604  /* Initialise the test buffers */
605  initTestBuffers( buffer, testBuffer, TESTBUFFER_SIZE );
606 
607  /* Check cryptlib's capabilities */
608  if( !checkLowlevelInfo( cryptDevice, cryptAlgo ) )
609  return( FALSE );
610 
611  /* If we're only doing a capability check, don't try anything else */
612  if( checkOnly )
613  return( TRUE );
614 
615  /* Since DH/ECDH and KEA only perform key agreement rather than a true
616  key exchange we can't test their encryption capabilities unless we're
617  using a custom-modified version of cryptlib */
618 #ifndef TEST_DH
619  if( cryptAlgo == CRYPT_ALGO_DH || cryptAlgo == CRYPT_ALGO_ECDH )
620  return( TRUE );
621 #endif /* TEST_DH */
622 
623  /* Test each mode of an algorithm. We have to be very careful about
624  destroying any objects we create before we exit, because objects left
625  active in a device will prevent it from being shut down once the
626  tests have completed */
627  do
628  {
629  /* Set up an encryption context, load a user key into it, and
630  perform a key setup */
631  switch( cryptAlgo )
632  {
633  case CRYPT_ALGO_DES:
634  status = loadContexts( &cryptContext, &decryptContext,
635  cryptDevice, cryptAlgo, cryptMode,
636  ( BYTE * ) "12345678", 8 );
637  break;
638 
639  case CRYPT_ALGO_IDEA:
640  case CRYPT_ALGO_AES:
641  status = loadContexts( &cryptContext, &decryptContext,
642  cryptDevice, cryptAlgo, cryptMode,
643  ( BYTE * ) "1234567887654321", 16 );
644  break;
645 
646  case CRYPT_ALGO_3DES:
647  status = loadContexts( &cryptContext, &decryptContext,
648  cryptDevice, cryptAlgo, cryptMode,
649  ( BYTE * ) "123456788765432112345678", 24 );
650  break;
651 
652  case CRYPT_ALGO_RC2:
653  case CRYPT_ALGO_RC4:
654  case CRYPT_ALGO_RC5:
655  case CRYPT_ALGO_BLOWFISH:
656  case CRYPT_ALGO_HMAC_MD5:
660  status = loadContexts( &cryptContext, &decryptContext,
661  cryptDevice, cryptAlgo, cryptMode,
662  ( BYTE * ) "1234567890098765432112345678900987654321", 40 );
663  break;
664 
665  case CRYPT_ALGO_MD5:
666  case CRYPT_ALGO_SHA:
667  case CRYPT_ALGO_SHA2:
669  status = loadContexts( &cryptContext, &decryptContext,
670  cryptDevice, cryptAlgo, CRYPT_MODE_NONE,
671  ( BYTE * ) "", 0 );
672  break;
673 
674 #ifdef TEST_DH
675  case CRYPT_ALGO_DH:
676  status = loadDHKey( cryptDevice, &cryptContext );
677  break;
678 #endif /* TEST_DH */
679 
680  case CRYPT_ALGO_RSA:
681  status = loadRSAContexts( cryptDevice, &cryptContext,
682  &decryptContext );
683  break;
684 
685  case CRYPT_ALGO_DSA:
686  status = loadDSAContexts( cryptDevice, &cryptContext,
687  &decryptContext );
688  break;
689 
690  case CRYPT_ALGO_ELGAMAL:
691  status = loadElgamalContexts( &cryptContext, &decryptContext );
692  break;
693 
694  case CRYPT_ALGO_ECDSA:
695  status = loadECDSAContexts( &cryptContext, &decryptContext );
696  break;
697 
698 #ifdef TEST_DH
699  case CRYPT_ALGO_ECDH:
700  status = loadECDHKey( cryptDevice, &cryptContext );
701  break;
702 #endif /* TEST_DH */
703 
704  default:
705  printf( "Unknown encryption algorithm ID %d, cannot perform "
706  "encryption test, line %d.\n", cryptAlgo, __LINE__ );
707  return( FALSE );
708  }
709  if( status == CRYPT_ERROR_NOTAVAIL )
710  {
711  /* It's a conventional algorithm for which this mode isn't
712  available, try a different mode */
713  cryptMode++;
714  continue;
715  }
716  if( !status )
717  return( FALSE );
718 
719  /* DLP-based algorithms can't be called directly from user code
720  because of the special data-formatting requirements */
721  if( cryptAlgo == CRYPT_ALGO_DSA || cryptAlgo == CRYPT_ALGO_ELGAMAL || \
722  cryptAlgo == CRYPT_ALGO_ECDSA )
723  {
724  destroyContexts( cryptDevice, cryptContext, decryptContext );
725  return( TRUE );
726  }
727 
728  /* Perform a test en/decryption */
729  status = testCrypt( cryptContext, decryptContext, buffer, isDevice,
730  FALSE );
731  if( cryptStatusError( status ) )
732  {
733  destroyContexts( cryptDevice, cryptContext, decryptContext );
734  if( isDevice && status == CRYPT_ERROR_NOTAVAIL )
735  {
736  /* Some primitive tokens or accelerators support only the
737  barest minimum of functionality, which may include being
738  able to create objects but not use them (e.g. public key
739  objects in a device which is just an RSA private-key
740  modexp engine). Because of this we may get a
741  CRYPT_ERROR_NOTAVAIL when we try and perform a low-level
742  crypto test, this isn't normally a problem for cryptlib
743  high-level objects because public-key ops are always done
744  in software, but when we explicitly try to do them in the
745  token it's a problem. Because of this we report a problem
746  but continue anyway */
747  puts( "The crypto device reported that this operation isn't "
748  "available even though it\nsupports the use of "
749  "encryption objects that implement this algorithm. "
750  "This\nis probably a bare-bones device that only "
751  "supports minimal functionality (eg\nprivate-key "
752  "decryption but not encryption)." );
753  continue;
754  }
755  return( FALSE );
756  }
757 
758  /* Make sure that everything went OK */
759  if( cryptAlgo >= CRYPT_ALGO_FIRST_HASH )
760  {
761  BYTE hash1[ CRYPT_MAX_HASHSIZE ], hash2[ CRYPT_MAX_HASHSIZE ];
762  int length1, length2;
763 
764  status = cryptGetAttributeString( cryptContext, CRYPT_CTXINFO_HASHVALUE,
765  hash1, &length1 );
767  hash2, &length2 );
768  if( cryptStatusError( status ) )
769  {
770  printf( "Couldn't get hash information, status = %d, "
771  "line %d.\n", status, __LINE__ );
772  destroyContexts( cryptDevice, cryptContext, decryptContext );
773  return( FALSE );
774  }
775  if( ( length1 != length2 ) || memcmp( hash1, hash2, length1 ) )
776  {
777  puts( "Error: Hash value of identical buffers differs." );
778  destroyContexts( cryptDevice, cryptContext, decryptContext );
779  return( FALSE );
780  }
781  if( !memcmp( hash1, "\x00\x00\x00\x00\x00\x00\x00\x00", 8 ) || \
782  !memcmp( hash2, "\x00\x00\x00\x00\x00\x00\x00\x00", 8 ) )
783  {
784  puts( "Error: Hash contains all zeroes." );
785  destroyContexts( cryptDevice, cryptContext, decryptContext );
786  return( FALSE );
787  }
788 
789  /* Make sure that we can get repeatable results after deleting
790  the hash/MAC and rehashing the data */
791  status = cryptDeleteAttribute( cryptContext,
793  if( cryptStatusOK( status ) )
794  status = cryptDeleteAttribute( decryptContext,
796  if( cryptStatusError( status ) )
797  {
798  printf( "Deletion of hash/MAC value failed with status %d, "
799  "line %d.\n", status, __LINE__ );
800  destroyContexts( cryptDevice, cryptContext, decryptContext );
801  return( FALSE );
802  }
803  if( cryptStatusError( testCrypt( cryptContext, decryptContext,
804  buffer, isDevice, FALSE ) ) )
805  {
806  destroyContexts( cryptDevice, cryptContext, decryptContext );
807  return( FALSE );
808  }
809  status = cryptGetAttributeString( cryptContext, CRYPT_CTXINFO_HASHVALUE,
810  hash1, &length1 );
811  if( cryptStatusError( status ) )
812  {
813  printf( "Couldn't get hash information for re-hashed data, "
814  "status = %d, line %d.\n", status, __LINE__ );
815  destroyContexts( cryptDevice, cryptContext, decryptContext );
816  return( FALSE );
817  }
818  if( ( length1 != length2 ) || memcmp( hash1, hash2, length1 ) )
819  {
820  puts( "Error: Hash value of re-hashed data differs." );
821  destroyContexts( cryptDevice, cryptContext, decryptContext );
822  return( FALSE );
823  }
824  }
825  else
826  {
827  /* If it's a PKC we'll have performed the check during the
828  encrypt/decrypt step */
829  if( cryptAlgo < CRYPT_ALGO_FIRST_PKC && \
830  !checkTestBuffers( buffer, testBuffer ) )
831  {
832  destroyContexts( cryptDevice, cryptContext, decryptContext );
833  return( FALSE );
834  }
835  }
836 
837  /* Remember that at least one test succeeded */
838  testSucceeded = TRUE;
839  if( cryptAlgo < CRYPT_ALGO_LAST_CONVENTIONAL )
840  modesTested[ cryptMode++ ] = TRUE;
841 
842  /* Clean up */
843  destroyContexts( cryptDevice, cryptContext, decryptContext );
844  }
845  while( cryptAlgo < CRYPT_ALGO_LAST_CONVENTIONAL && \
846  cryptMode < CRYPT_MODE_LAST );
847 
848  /* If it's a conventional algorithm, report the encryption modes that
849  were tested */
850  if( cryptAlgo < CRYPT_ALGO_LAST_CONVENTIONAL )
851  {
852  printf( " Encryption modes tested:" );
853  if( modesTested[ CRYPT_MODE_ECB ] )
854  printf( " ECB" );
855  if( modesTested[ CRYPT_MODE_CBC ] )
856  printf( " CBC" );
857  if( modesTested[ CRYPT_MODE_CFB ] )
858  printf( " CFB" );
859  if( modesTested[ CRYPT_MODE_OFB ] )
860  printf( " OFB" );
861  if( modesTested[ CRYPT_MODE_GCM ] )
862  printf( " GCM" );
863  puts( "." );
864  }
865 
866  /* Make sure that at least one of the algorithm's modes was tested */
867  if( !testSucceeded )
868  {
869  puts( "No processing modes were found for this algorithm.\n" );
870  return( FALSE );
871  }
872 
873  return( TRUE );
874  }
875 
876 /* Test the ability of the RSA key-load code to reconstruct a full RSA key
877  from only the minimal non-CRT components */
878 
879 int testRSAMinimalKey( void )
880  {
881  CRYPT_CONTEXT cryptContext, decryptContext;
882  BYTE buffer[ TESTBUFFER_SIZE ], testBuffer[ TESTBUFFER_SIZE ];
883  int status;
884 
885  puts( "Testing ability to recover CRT components for RSA private key..." );
886 
887  /* Load the RSA contexts from the minimal (non-CRT) RSA key */
888  status = loadRSAContextsEx( CRYPT_UNUSED, &cryptContext, &decryptContext,
890  TRUE );
891  if( !status )
892  return( FALSE );
893 
894  /* Initialise the test buffers */
895  initTestBuffers( buffer, testBuffer, TESTBUFFER_SIZE );
896 
897  /* Make sure that we can encrypt and decrypt with the reconstituted CRT
898  private key */
899  status = testCrypt( cryptContext, decryptContext, buffer, FALSE, FALSE );
900  if( cryptStatusError( status ) )
901  return( FALSE );
902 
903  /* Clean up */
904  destroyContexts( CRYPT_UNUSED, cryptContext, decryptContext );
905 
906  puts( "RSA CRT component recovery test succeeded." );
907  return( TRUE );
908  }
909 
910 /****************************************************************************
911 * *
912 * Performance Tests *
913 * *
914 ****************************************************************************/
915 
916 /* General performance characteristics test. Since high-precision timing is
917  rather OS-dependent, we only enable this under Windows where we've got
918  guaranteed high-res timer access */
919 
920 #if defined( __WINDOWS__ ) && defined( _MSC_VER ) && ( _MSC_VER >= 1100 )
921 
922 #include <math.h> /* For sqrt() for standard deviation */
923 
924 #define NO_TESTS 25
925 
926 static unsigned long timeDiff( unsigned long startTime )
927  {
928  unsigned long timeLSB;
929 
930 #if 1
931  LARGE_INTEGER performanceCount;
932 
933  /* Sensitive to context switches */
934  QueryPerformanceCounter( &performanceCount );
935  timeLSB = performanceCount.LowPart;
936 #else
937  FILETIME dummyTime, kernelTime, userTime;
938  int status;
939 
940  /* Only accurate to 10ms, returns constant values in VC++ debugger */
941  GetThreadTimes( GetCurrentThread(), &dummyTime, &dummyTime,
942  &kernelTime, &userTime );
943  timeLSB = userTime.dwLowDateTime;
944 #endif /* 0 */
945 
946  if( !startTime )
947  return( timeLSB );
948  if( startTime < timeLSB )
949  return( timeLSB - startTime );
950  return( ( 0xFFFFFFFF - startTime ) + 1 + timeLSB );
951  }
952 
953 /* Print timing info. This gets a bit hairy because we're actually counting
954  timer ticks rather than thread times, which means we'll be affected by
955  things like context switches. There are two approaches to this:
956 
957  1. Take the fastest time, which will be the time least affected by system
958  overhead.
959 
960  2. Apply standard statistical techniques to weed out anomalies. Since
961  this is just for testing purposes all we do is discard any results
962  out by more than 10%, which is crude but reasonably effective. A
963  more rigorous approach is to discards results more than n standard
964  deviations out, but this gets screwed up by the fact that a single
965  context switch of 20K ticks can throw out results from an execution
966  time of only 50 ticks. In any case (modulo context switches) the
967  fastest, 10%-out, and 2 SD out times are all within about 1% of each
968  other, so all methods are roughly equally accurate */
969 
970 static void printTimes( long times[ NO_TESTS + 1 ][ 8 ] )
971  {
972  int i;
973 
974  for( i = 0; i < 7; i++ )
975  {
976  long timeSum = 0, timeAvg, timeDelta;
977  long timeMin = 1000000L, timeCorrSum10 = 0, timeCorrSumSD = 0;
978 #ifdef USE_SD
979  double stdDev;
980 #endif /* USE_SD */
981  int j, timesCount10 = 0, timesCountSD = 0;
982 
983  /* Find the mean execution time */
984  for( j = 1; j < NO_TESTS + 1; j++ )
985  timeSum += times[ j ][ i ];
986  timeAvg = timeSum / NO_TESTS;
987  timeDelta = timeSum / 10; /* 10% variation */
988  if( timeSum == 0 )
989  {
990  /* Some ciphers can't provide results for some cases (e.g.
991  AES for 8-byte blocks) */
992  printf( " " );
993  continue;
994  }
995 
996  /* Find the fastest overall time */
997  for( j = 1; j < NO_TESTS + 1; j++ )
998  if( times[ j ][ i ] < timeMin )
999  timeMin = times[ j ][ i ];
1000 
1001  /* Find the mean time, discarding anomalous results more than 10%
1002  out */
1003  for( j = 1; j < NO_TESTS + 1; j++ )
1004  if( times[ j ][ i ] > timeAvg - timeDelta && \
1005  times[ j ][ i ] < timeAvg + timeDelta )
1006  {
1007  timeCorrSum10 += times[ j ][ i ];
1008  timesCount10++;
1009  }
1010  printf( "%6d", timeCorrSum10 / timesCount10 );
1011 #if 0 /* Print difference to fastest time, usually only around 1% */
1012  printf( "(%4d)", ( timeCorrSum10 / timesCount10 ) - timeMin );
1013 #endif /* 0 */
1014 
1015 #ifdef USE_SD
1016  /* Find the standard deviation */
1017  for( j = 1; j < NO_TESTS + 1; j++ )
1018  {
1019  const long timeDev = times[ j ][ i ] - timeAvg;
1020 
1021  timeCorrSumSD += ( timeDev * timeDev );
1022  }
1023  stdDev = timeCorrSumSD / NO_TESTS;
1024  stdDev = sqrt( stdDev );
1025 
1026  /* Find the mean time, discarding anomalous results more than two
1027  standard deviations out */
1028  timeCorrSumSD = 0;
1029  timeDelta = ( long ) stdDev * 2;
1030  for( j = 1; j < NO_TESTS + 1; j++ )
1031  if( times[ j ][ i ] > timeAvg - timeDelta && \
1032  times[ j ][ i ] < timeAvg + timeDelta )
1033  {
1034  timeCorrSumSD += times[ j ][ i ];
1035  timesCountSD++;
1036  }
1037  if( timesCountSD == 0 )
1038  timesCountSD++; /* Context switch, fudge it */
1039  printf( "%6d", timeCorrSumSD / timesCountSD );
1040 
1041 #if 1 /* Print difference to fastest and mean times, usually only around
1042  1% */
1043  printf( " (dF = %4d, dM = %4d)\n",
1044  ( timeCorrSumSD / timesCountSD ) - timeMin,
1045  abs( ( timeCorrSumSD / timesCountSD ) - \
1046  ( timeCorrSum10 / timesCount10 ) ) );
1047 #endif /* 0 */
1048 #endif /* USE_SD */
1049  }
1050  printf( "\n" );
1051  }
1052 
1053 static long encOne( const CRYPT_CONTEXT cryptContext, BYTE *buffer,
1054  const int length )
1055  {
1056  unsigned long timeVal;
1057  int status;
1058 
1059  memset( buffer, '*', length );
1060  timeVal = timeDiff( 0 );
1061  status = cryptEncrypt( cryptContext, buffer, length );
1062  return( timeDiff( timeVal ) );
1063  }
1064 
1065 static int encTest( const CRYPT_CONTEXT cryptContext,
1066  const CRYPT_ALGO_TYPE cryptAlgo, BYTE *buffer,
1067  long times[] )
1068  {
1069  int index = 0;
1070 
1071  times[ index++ ] = ( cryptAlgo != CRYPT_ALGO_AES ) ? \
1072  encOne( cryptContext, buffer, 8 ) : 0;
1073  times[ index++ ] = encOne( cryptContext, buffer, 16 );
1074  times[ index++ ] = encOne( cryptContext, buffer, 64 );
1075  times[ index++ ] = encOne( cryptContext, buffer, 1024 );
1076  times[ index++ ] = encOne( cryptContext, buffer, 4096 );
1077  times[ index++ ] = encOne( cryptContext, buffer, 8192 );
1078  times[ index++ ] = encOne( cryptContext, buffer, 65536L );
1079  return( TRUE );
1080  }
1081 
1082 static int encTests( const CRYPT_DEVICE cryptDevice,
1083  const CRYPT_ALGO_TYPE cryptAlgo,
1084  const CRYPT_ALGO_TYPE cryptMode,
1085  BYTE *buffer )
1086  {
1088  unsigned long times[ NO_TESTS + 1 ][ 8 ], timeVal, timeSum = 0;
1089  int i, status;
1090 
1091  memset( buffer, 0, 100000L );
1092 
1093  /* Set up the context for use */
1094  if( !checkLowlevelInfo( cryptDevice, cryptAlgo ) )
1095  return( FALSE );
1096  for( i = 0; i < 10; i++ )
1097  {
1098  timeVal = timeDiff( 0 );
1099  status = loadContexts( &cryptContext, NULL, cryptDevice,
1100  cryptAlgo, cryptMode,
1101  ( BYTE * ) "12345678901234567890",
1102  ( cryptAlgo == CRYPT_ALGO_DES ) ? 8 : \
1103  ( cryptAlgo == CRYPT_ALGO_3DES || \
1104  cryptAlgo == CRYPT_ALGO_RC4 || \
1105  cryptAlgo == CRYPT_ALGO_AES ) ? 16 : 0 );
1106  timeVal = timeDiff( timeVal );
1107  if( status == CRYPT_ERROR_NOTAVAIL || !status )
1108  return( FALSE );
1109  timeSum += timeVal;
1110  if( i < 9 )
1111  cryptDestroyContext( cryptContext );
1112  }
1113  printf( "Setup time = %d ticks.\n", timeSum / 10 );
1114  puts( " 8 16 64 1K 4K 8K 64K" );
1115  puts( " ---- ---- ---- ---- ---- ---- ----" );
1116 
1117  /* Run the encryption tests NO_TESTS times, discard the first set of
1118  results since the cache will be empty at that point */
1119  for( i = 0; i < NO_TESTS + 1; i++ )
1120  encTest( cryptContext, cryptAlgo, buffer, times[ i ] );
1121  printTimes( times );
1122 
1123  /* Re-run the encryption tests with a 1-byte misalignment */
1124  for( i = 0; i < NO_TESTS + 1; i++ )
1125  encTest( cryptContext, cryptAlgo, buffer + 1, times[ i ] );
1126  printTimes( times );
1127 
1128  /* Re-run the encryption tests with a 4-byte misalignment */
1129  for( i = 0; i < NO_TESTS + 1; i++ )
1130  encTest( cryptContext, cryptAlgo, buffer + 4, times[ i ] );
1131  printTimes( times );
1132 
1133  /* Re-run the test 1000 times with various buffer alignments */
1134  timeVal = 0;
1135  for( i = 0; i < 1000; i++ )
1136  timeVal += encOne( cryptContext, buffer, 1024 );
1137  printf( "Aligned: %d ", timeVal / 1000 );
1138  timeVal = 0;
1139  for( i = 0; i < 1000; i++ )
1140  timeVal += encOne( cryptContext, buffer + 1, 1024 );
1141  printf( "misaligned + 1: %d ", timeVal / 1000 );
1142  timeVal = 0;
1143  for( i = 0; i < 1000; i++ )
1144  timeVal += encOne( cryptContext, buffer + 4, 1024 );
1145  printf( "misaligned + 4: %d.\n", timeVal / 1000 );
1146 
1147  return( TRUE );
1148  }
1149 
1150 void performanceTests( const CRYPT_DEVICE cryptDevice )
1151  {
1152  LARGE_INTEGER performanceCount;
1153  BYTE *buffer;
1154 
1155  QueryPerformanceFrequency( &performanceCount );
1156  printf( "Clock ticks %d times per second.\n", performanceCount.LowPart );
1157  if( ( buffer = malloc( 100000L ) ) == NULL )
1158  {
1159  puts( "Couldn't 100K allocate test buffer." );
1160  return;
1161  }
1162  encTests( CRYPT_UNUSED, CRYPT_ALGO_DES, CRYPT_MODE_ECB, buffer );
1163  encTests( CRYPT_UNUSED, CRYPT_ALGO_DES, CRYPT_MODE_CBC, buffer );
1164  encTests( CRYPT_UNUSED, CRYPT_ALGO_3DES, CRYPT_MODE_ECB, buffer );
1165  encTests( CRYPT_UNUSED, CRYPT_ALGO_3DES, CRYPT_MODE_CBC, buffer );
1166  encTests( CRYPT_UNUSED, CRYPT_ALGO_RC4, CRYPT_MODE_OFB, buffer );
1167  encTests( CRYPT_UNUSED, CRYPT_ALGO_AES, CRYPT_MODE_CBC, buffer );
1168  encTests( CRYPT_UNUSED, CRYPT_ALGO_MD5, CRYPT_MODE_NONE, buffer );
1169  encTests( CRYPT_UNUSED, CRYPT_ALGO_SHA, CRYPT_MODE_NONE, buffer );
1170  free( buffer );
1171  }
1172 #endif /* Win32 with VC++ */
1173 
1174 #endif /* TEST_LOWLEVEL || TEST_KEYSET */