cryptlib  3.4.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Macros
keyfile.c
Go to the documentation of this file.
1 /****************************************************************************
2 * *
3 * cryptlib File Keyset Test Routines *
4 * Copyright Peter Gutmann 1995-2009 *
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 /* External flags that indicate that the key read/update routines worked OK.
20  This is set by earlier self-test code, if it isn't set some of the tests
21  are disabled */
22 
23 extern int keyReadOK, doubleCertOK;
24 
25 #ifdef TEST_KEYSET
26 
27 /****************************************************************************
28 * *
29 * Utility Routines *
30 * *
31 ****************************************************************************/
32 
33 /* Get an algorithm name and the label for the key for that algorithm */
34 
35 static const char *getAlgoName( const CRYPT_ALGO_TYPE cryptAlgo )
36  {
37  switch( cryptAlgo )
38  {
39  case CRYPT_ALGO_RSA:
40  return( "RSA" );
41 
42  case CRYPT_ALGO_DSA:
43  return( "DSA" );
44 
45  case CRYPT_ALGO_ELGAMAL:
46  return( "Elgamal" );
47 
48  case CRYPT_ALGO_ECDH:
49  return( "ECDH" );
50 
51  case CRYPT_ALGO_ECDSA:
52  return( "ECDSA" );
53  }
54 
55  return( "<Unknown>" );
56  }
57 
58 static const C_STR getAlgoLabel( const CRYPT_ALGO_TYPE cryptAlgo )
59  {
60  switch( cryptAlgo )
61  {
62  case CRYPT_ALGO_RSA:
63  return( RSA_PRIVKEY_LABEL );
64 
65  case CRYPT_ALGO_DSA:
66  return( DSA_PRIVKEY_LABEL );
67 
68  case CRYPT_ALGO_ELGAMAL:
69  return( ELGAMAL_PRIVKEY_LABEL );
70 
71  case CRYPT_ALGO_ECDH:
72  return( ECDSA_PRIVKEY_LABEL );
73 
74  case CRYPT_ALGO_ECDSA:
75  return( ECDSA_PRIVKEY_LABEL );
76  }
77 
78  return( TEXT( "<Unknown>" ) );
79  }
80 
81 /* Load a private-key context for a particular algorithm */
82 
83 static int loadPrivateKeyContext( CRYPT_CONTEXT *cryptContext,
84  const CRYPT_ALGO_TYPE cryptAlgo )
85  {
86  switch( cryptAlgo )
87  {
88  case CRYPT_ALGO_RSA:
89  return( loadRSAContexts( CRYPT_UNUSED, NULL, cryptContext ) );
90 
91  case CRYPT_ALGO_DSA:
92  return( loadDSAContexts( CRYPT_UNUSED, cryptContext, NULL ) );
93 
94  case CRYPT_ALGO_ELGAMAL:
95  return( loadElgamalContexts( NULL, cryptContext ) );
96 
97  case CRYPT_ALGO_ECDSA:
98  return( loadECDSAContexts( cryptContext, NULL ) );
99  }
100 
101  printf( "Algorithm %d not available, line %d.\n", cryptAlgo, __LINE__ );
102  return( FALSE );
103  }
104 
105 /* Make sure that an item read from a keyset is a certificate */
106 
107 static int checkCertPresence( const CRYPT_HANDLE cryptHandle,
108  const char *certTypeName,
110  {
111  int value, status;
112 
113  /* Make sure that what we've got is a certificate */
114  status = cryptGetAttribute( cryptHandle, CRYPT_CERTINFO_CERTTYPE,
115  &value );
116  if( cryptStatusError( status ) || value != certType )
117  {
118  printf( "Returned object isn't a %s, line %d.\n", certTypeName,
119  __LINE__ );
120  return( FALSE );
121  }
122 
123  /* Make sure that we can't use the read key (the certificate constrains
124  it from being used externally) */
125  status = testCrypt( cryptHandle, cryptHandle, NULL, FALSE, TRUE );
126  if( status != CRYPT_ERROR_NOTAVAIL && status != CRYPT_ERROR_PERMISSION )
127  {
128  puts( "Attempt to perform external operation on context with "
129  "internal-only action\npermissions succeeded. " );
130  return( FALSE );
131  }
132 
133  return( TRUE );
134  }
135 
136 /* Copy a source file to a destination file, corrupting a given byte in the
137  process. This is used to test the ability of the keyset-processing code
138  to detect data manipulation in keyset data */
139 
140 static int copyModifiedFile( const C_STR srcFileName,
141  const C_STR destFileName, const int bytePos )
142  {
143  FILE *filePtr;
145  int count = 0;
146 
147  /* Read the source file into the data buffer */
148  if( ( filePtr = fopen( convertFileName( srcFileName ), "rb" ) ) != NULL )
149  {
150  count = fread( buffer, 1, BUFFER_SIZE, filePtr );
151  if( count >= BUFFER_SIZE )
152  count = 0;
153  fclose( filePtr );
154  }
155  if( count <= 0 )
156  return( FALSE );
157 
158  /* Corrupt a specific byte in the file */
159  buffer[ bytePos ] ^= 0xFF;
160 
161  /* Write the changed result to the output buffer */
162  if( ( filePtr = fopen( convertFileName( destFileName ), "wb" ) ) != NULL )
163  {
164  int writeCount;
165 
166  writeCount = fwrite( buffer, 1, count, filePtr );
167  if( writeCount != count )
168  count = 0;
169  fclose( filePtr );
170  }
171 
172  return( ( count > 0 ) ? TRUE : FALSE );
173  }
174 
175 /****************************************************************************
176 * *
177 * PGP/PKCS #12 Key Read/Write Tests *
178 * *
179 ****************************************************************************/
180 
181 /* Get a public key from a PGP keyring */
182 
183 static int getPGPPublicKey( const KEYFILE_TYPE keyFileType,
184  const C_STR keyFileTemplate,
185  const char *description )
186  {
187  CRYPT_KEYSET cryptKeyset;
189  FILE *filePtr;
190  char fileName[ BUFFER_SIZE ];
191 #ifdef UNICODE_STRINGS
192  wchar_t wcBuffer[ FILENAME_BUFFER_SIZE ];
193 #endif /* UNICODE_STRINGS */
194  const C_STR keysetName = getKeyfileName( keyFileType, FALSE );
195  int status;
196 
197  /* If this is the first file read, check that the file actually exists
198  so we can return an appropriate error message */
199  if( keyFileType == KEYFILE_PGP )
200  {
201  if( ( filePtr = fopen( convertFileName( keysetName ),
202  "rb" ) ) == NULL )
203  return( CRYPT_ERROR_FAILED );
204  fclose( filePtr );
205  keyReadOK = FALSE;
206  }
207 
208  /* If the caller has overridden the keyfile to use, use the caller-
209  supplied name */
210  if( keyFileTemplate != NULL )
211  {
212  filenameFromTemplate( fileName, keyFileTemplate, 1 );
213 #ifdef UNICODE_STRINGS
214  mbstowcs( wcBuffer, fileName, strlen( fileName ) + 1 );
215  keysetName = wcBuffer;
216 #else
217  keysetName = fileName;
218 #endif /* UNICODE_STRINGS */
219  }
220 
221  printf( "Testing %s public key read...\n", description );
222 
223  /* Open the keyset */
224  status = cryptKeysetOpen( &cryptKeyset, CRYPT_UNUSED, CRYPT_KEYSET_FILE,
225  keysetName, CRYPT_KEYOPT_READONLY );
226  if( cryptStatusError( status ) )
227  {
228  printf( "cryptKeysetOpen() failed with error code %d, line %d.\n",
229  status, __LINE__ );
230  return( FALSE );
231  }
232 
233  /* Get the key. The read of the special-case PGP keyring tests the
234  ability to handle over-long key packet groups so this should return
235  a not-found error due to the packets being skipped */
236  status = cryptGetPublicKey( cryptKeyset, &cryptContext, CRYPT_KEYID_NAME,
237  getKeyfileUserID( keyFileType, FALSE ) );
238  if( ( keyFileType == KEYFILE_PGP_SPECIAL && \
239  status != CRYPT_ERROR_NOTFOUND ) || \
240  ( keyFileType != KEYFILE_PGP_SPECIAL && \
241  cryptStatusError( status ) ) )
242  {
243  printExtError( cryptKeyset, "cryptGetPublicKey()", status,
244  __LINE__ );
245  return( FALSE );
246  }
247  cryptDestroyContext( cryptContext );
248 
249  /* Close the keyset */
250  status = cryptKeysetClose( cryptKeyset );
251  if( cryptStatusError( status ) )
252  {
253  printf( "cryptKeysetClose() failed with error code %d, line %d.\n",
254  status, __LINE__ );
255  return( FALSE );
256  }
257 
258  printf( "Read of public key from %s keyring succeeded.\n\n",
259  description );
260  return( TRUE );
261  }
262 
263 int testGetPGPPublicKey( void )
264  {
265  /* See testGetPGPPrivateKey() for the descriptions of the files */
266  if( !getPGPPublicKey( KEYFILE_PGP, NULL, "PGP" ) )
267  return( FALSE );
268  if( !getPGPPublicKey( KEYFILE_OPENPGP_HASH, NULL, "OpenPGP (GPG/hashed key)" ) )
269  return( FALSE );
270  if( !getPGPPublicKey( KEYFILE_OPENPGP_AES, NULL, "OpenPGP (GPG/AES-256 key)" ) )
271  return( FALSE );
272  if( !getPGPPublicKey( KEYFILE_OPENPGP_RSA, NULL, "OpenPGP (GPG/RSA key)" ) )
273  return( FALSE );
274  if( !getPGPPublicKey( KEYFILE_NAIPGP, NULL, "OpenPGP (NAI)" ) )
275  return( FALSE );
276  return( getPGPPublicKey( KEYFILE_PGP_SPECIAL, PGPKEY_FILE_TEMPLATE, "Complex PGP key" ) );
277  }
278 
279 /* Get a private key from a PGP keyring */
280 
281 static int getPGPPrivateKey( const KEYFILE_TYPE keyFileType,
282  const char *description )
283  {
284  CRYPT_KEYSET cryptKeyset;
286  const C_STR keysetName = getKeyfileName( keyFileType, TRUE );
287  const C_STR password = getKeyfilePassword( keyFileType );
288  int status;
289 
290  printf( "Testing %s private key read...\n", description );
291 
292  /* Open the keyset */
293  status = cryptKeysetOpen( &cryptKeyset, CRYPT_UNUSED, CRYPT_KEYSET_FILE,
294  keysetName, CRYPT_KEYOPT_READONLY );
295  if( cryptStatusError( status ) )
296  {
297  printf( "cryptKeysetOpen() failed with error code %d, line %d.\n",
298  status, __LINE__ );
299  return( FALSE );
300  }
301 
302  /* Get the key. First we try it without a password, if that fails we
303  retry it with the password - this tests a lot of the private-key get
304  functionality including things like key cacheing */
305  status = cryptGetPrivateKey( cryptKeyset, &cryptContext, CRYPT_KEYID_NAME,
306  getKeyfileUserID( keyFileType, TRUE ), NULL );
307  if( status == CRYPT_ERROR_WRONGKEY )
308  {
309  /* We need a password for this private key, get it from the user and
310  get the key again */
311  status = cryptGetPrivateKey( cryptKeyset, &cryptContext,
313  getKeyfileUserID( keyFileType, TRUE ),
314  password );
315  }
316  if( cryptStatusError( status ) )
317  {
318  printExtError( cryptKeyset, "cryptGetPrivateKey()", status,
319  __LINE__ );
320  return( FALSE );
321  }
322 
323  /* Make sure that we can use the key that we've read. We can only do this
324  with PGP 2.x keys, OpenPGP's peculiar multi-keys identify two (or more)
325  keys with the same label and we can't specify (at this level) which
326  key we want to use (the enveloping code can be more specific and so
327  doesn't run into this problem) */
328  if( keyFileType == KEYFILE_PGP )
329  {
330  status = testCrypt( cryptContext, cryptContext, NULL, FALSE, FALSE );
331  if( cryptStatusError( status ) )
332  return( FALSE );
333  }
334  cryptDestroyContext( cryptContext );
335 
336  /* Close the keyset */
337  status = cryptKeysetClose( cryptKeyset );
338  if( cryptStatusError( status ) )
339  {
340  printf( "cryptKeysetClose() failed with error code %d, line %d.\n",
341  status, __LINE__ );
342  return( FALSE );
343  }
344 
345  /* The public and private key reads worked, remember this for later when
346  we use the keys in other tests */
347  keyReadOK = TRUE;
348 
349  printf( "Read of private key from %s keyring succeeded.\n\n",
350  description );
351  return( TRUE );
352  }
353 
354 int testGetPGPPrivateKey( void )
355  {
356  /* PGP 2.x file, RSA with IDEA, secring.pgp */
357  if( !getPGPPrivateKey( KEYFILE_PGP, "PGP" ) )
358  return( FALSE );
359 
360  /* OpenPGP file, DSA+Elgamal with 3DES, sec_hash.gpg. Create with:
361 
362  gpg --gen-key --homedir . --s2k-cipher-algo 3des
363 
364  Select DSA+Elgamal, size 1024 bits, key does not expire,
365  name = Test1, email = [email protected], comment blank,
366  password = test1 */
367  if( !getPGPPrivateKey( KEYFILE_OPENPGP_HASH, "OpenPGP (GPG/hashed key)" ) )
368  return( FALSE );
369 
370  /* OpenPGP file, DSA+Elgamal with AES, sec_aes.skr */
371  if( !getPGPPrivateKey( KEYFILE_OPENPGP_AES, "OpenPGP (GPG/AES-256 key)" ) )
372  return( FALSE );
373 
374  /* OpenPGP file, RSA+RSA with 3DES and SHA256, sec_rsa.gpg. Create with:
375 
376  gpg --gen-key --homedir . --s2k-cipher-algo 3des --s2k-digest-algo sha256
377 
378  Select RSA, size 2048 bits, key does not expire, name = Test1,
379  email = [email protected], comment blank, password = test1 */
380  if( !getPGPPrivateKey( KEYFILE_OPENPGP_RSA, "OpenPGP (GPG/RSA key)" ) )
381  return( FALSE );
382 
383  /* OpenPGP file, RSA with IDEA, sec_nai.skr */
384  return( getPGPPrivateKey( KEYFILE_NAIPGP, "OpenPGP (NAI)" ) );
385  }
386 
387 /* Get a key from a PKCS #12 file. Because of the security problems
388  associated with this format, the code only checks the data format but
389  doesn't try to read or use the keys. If anyone wants this, they'll
390  have to add the code themselves. Your security warranty is automatically
391  void when you implement this */
392 
393 static int borkenKeyImport( const int fileNo )
394  {
395  CRYPT_KEYSET cryptKeyset;
397  const C_STR userID;
398  const C_STR password;
399  BYTE buffer[ BUFFER_SIZE ];
400  int status;
401 
402  /* Set up the file access information:
403 
404  Keyset #1 = CryptoAPI via OpenSSL, privKey with ID data and 3DES,
405  then anonymous cert with RC2/40.
406  Keyset #2 = CryptoAPI, privKey with ID data and 3DES, then
407  anonymous cert with RC2/40. The private key is identified via a
408  GUID which we can't do much with so we pass in the special-case
409  userID "[none]" meaning "return the first key that we find".
410  Keyset #3 = Unknown source, cert chain in plaintext with ID data,
411  then privKey with ID data and 3DES. The userID for the private
412  key is the single hex byte 0x8C, again we use "[none]" for this.
413  Keyset #4 = OpenSSL, anonymous cert with RC2/40, then privKey with
414  ID data and 3DES.
415  Keyset #5 = Unknown source (possibly OpenSSL), anonymous cert with
416  RC2/40, then privKey with ID data and 3DES. Unlike keyset #4
417  the ID data doesn't include a userID, so we again have to resort
418  to "[none]" to read it.
419  Keyset $6 = Unknown source, from some CA that generates the private
420  key for you rather than allowing you to generate it. Contains
421  mostly indefinite-length encodings of data, currently not
422  readable, see the comments in keyset/pkcs12_rd.c for more
423  details */
424  switch( fileNo )
425  {
426  case 1:
427  userID = TEXT( "test pkcs#12" );
428  password = TEXT( "test" );
429  break;
430 
431  case 2:
432  userID = TEXT( "[none]" ); /* Label = GUID */
433  password = TEXT( "<unknown>" ); /* Unknown, RC2=2C 28 14 C4 01 */
434  break;
435 
436  case 3:
437  userID = TEXT( "[none]" ); /* No label, ID = 0x8C */
438  password = TEXT( "7OPWKMIX" );
439  break;
440 
441  case 4:
442  userID = TEXT( "server" );
443  password = TEXT( "cryptlib" );
444  break;
445 
446  case 5:
447  userID = TEXT( "[none]" ); /* No label, ID = hash */
448  password = TEXT( "password" );
449  break;
450 
451  case 6:
452  userID = TEXT( "SignLabel" );
453  password = TEXT( "vpsign" );
454  /* Drop through */
455 
456  default:
457  assert( 0 );
458  return( FALSE );
459  }
460 
461  /* Open the file keyset. Note that we print the usual test message only
462  after we try and open the keyset, in order to avoid a cascade of PKCS
463  #12 file non-opened messages */
464  filenameFromTemplate( buffer, PKCS12_FILE_TEMPLATE, fileNo );
465  status = cryptKeysetOpen( &cryptKeyset, CRYPT_UNUSED, CRYPT_KEYSET_FILE,
466  buffer, CRYPT_KEYOPT_READONLY );
467  if( cryptStatusError( status ) && status == CRYPT_ERROR_NOTAVAIL )
468  {
469  /* If support for this isn't enabled, just exit quietly */
470  return( TRUE );
471  }
472  printf( "Testing PKCS #12 file #%d import...\n", fileNo );
473  if( cryptStatusError( status ) )
474  {
475  printf( "cryptKeysetOpen() failed with error code %d, line %d.\n",
476  status, __LINE__ );
477  return( FALSE );
478  }
479 
480  /* Get the key */
481  status = cryptGetPrivateKey( cryptKeyset, &cryptContext, CRYPT_KEYID_NAME,
482  userID, password );
483  if( cryptStatusError( status ) )
484  {
485  switch( fileNo )
486  {
487  case 1:
488  /* This file has a 512-bit key and will give a
489  CRYPT_ERROR_NOSECURE on import */
490  if( status == CRYPT_ERROR_NOSECURE )
491  status = CRYPT_OK;
492  break;
493 
494  case 2:
495  /* This file has an unknown password, although the cracked
496  RC2/40 key for it is 2C 28 14 C4 01 */
497  if( status == CRYPT_ERROR_WRONGKEY )
498  status = CRYPT_OK;
499  break;
500 
501  case 3:
502  /* This file contains an invalid private key, specifically
503  ( q * u ) mod p != 1 (!!!) */
504  if( status == CRYPT_ERROR_INVALID )
505  status = CRYPT_OK;
506  break;
507  }
508  if( cryptStatusError( status ) )
509  {
510  printExtError( cryptKeyset, "cryptGetPrivateKey()", status,
511  __LINE__ );
512  return( FALSE );
513  }
514  }
515  else
516  {
517  /* Make sure that we got a certificate alongside the private key */
518  if( !checkCertPresence( cryptContext, "private key with certificate",
520  return( FALSE );
521  cryptDestroyContext( cryptContext );
522  }
523 
524  /* Close the keyset */
525  status = cryptKeysetClose( cryptKeyset );
526  if( cryptStatusError( status ) )
527  {
528  printf( "cryptKeysetClose() failed with error code %d, line %d.\n",
529  status, __LINE__ );
530  return( FALSE );
531  }
532 
533  printf( "Read of key from PKCS #12 file #%d succeeded.\n\n", fileNo );
534  return( TRUE );
535  }
536 
537 int testReadAltFileKey( void )
538  {
539  int i;
540 
541  for( i = 1; i <= 5; i++ )
542  {
543  if( !borkenKeyImport( i ) )
544  return( FALSE );
545  }
546 
547  return( TRUE );
548  }
549 
550 /****************************************************************************
551 * *
552 * Public/Private Key Read/Write Tests *
553 * *
554 ****************************************************************************/
555 
556 /* Read/write a private key from a file */
557 
558 static int readFileKey( const CRYPT_ALGO_TYPE cryptAlgo,
559  const BOOLEAN useAltKeyFile )
560  {
561  CRYPT_KEYSET cryptKeyset;
563  int status;
564 
565  printf( "Testing %s private key read from %skey file...\n",
566  getAlgoName( cryptAlgo ), useAltKeyFile ? "alternative " : "" );
567 
568  /* Open the file keyset */
569  status = cryptKeysetOpen( &cryptKeyset, CRYPT_UNUSED, CRYPT_KEYSET_FILE,
570  useAltKeyFile ? TEST_PRIVKEY_ALT_FILE : \
573  if( cryptStatusError( status ) )
574  {
575  if( useAltKeyFile && status == CRYPT_ERROR_NOTAVAIL )
576  {
577  /* If the format isn't supported, this isn't a problem */
578  puts( "Read of RSA private key from alternative key file "
579  "skipped.\n" );
580  return( TRUE );
581  }
582  printf( "cryptKeysetOpen() failed with error code %d, line %d.\n",
583  status, __LINE__ );
584  return( FALSE );
585  }
586 
587  /* Read the key from the file */
588  status = cryptGetPrivateKey( cryptKeyset, &cryptContext,
589  CRYPT_KEYID_NAME, getAlgoLabel( cryptAlgo ),
591  if( cryptStatusError( status ) )
592  {
593  printExtError( cryptKeyset, "cryptGetPrivateKey()", status,
594  __LINE__ );
595  return( FALSE );
596  }
597 
598  /* Make sure that we can use the read key */
599  if( cryptAlgo == CRYPT_ALGO_RSA )
600  {
601  status = testCrypt( cryptContext, cryptContext, NULL, FALSE, FALSE );
602  if( cryptStatusError( status ) )
603  return( FALSE );
604  }
605  cryptDestroyContext( cryptContext );
606 
607  /* Close the keyset */
608  status = cryptKeysetClose( cryptKeyset );
609  if( cryptStatusError( status ) )
610  {
611  printf( "cryptKeysetClose() failed with error code %d, line %d.\n",
612  status, __LINE__ );
613  return( FALSE );
614  }
615 
616  printf( "Read of %s private key from %skey file succeeded.\n\n",
617  getAlgoName( cryptAlgo ), useAltKeyFile ? "alternative " : "" );
618  return( TRUE );
619  }
620 
621 static int writeFileKey( const CRYPT_ALGO_TYPE cryptAlgo,
622  const BOOLEAN useAltKeyFile,
623  const BOOLEAN generateKey )
624  {
625  CRYPT_KEYSET cryptKeyset;
626  CRYPT_CONTEXT privateKeyContext;
627  int status;
628 
629  printf( "Testing %s private key write to %skey file...\n",
630  getAlgoName( cryptAlgo ), useAltKeyFile ? "alternative " : "" );
631 
632  /* Create the private key context */
633  if( generateKey )
634  {
635  status = cryptCreateContext( &privateKeyContext, CRYPT_UNUSED,
636  cryptAlgo );
637  if( cryptStatusOK( status ) )
638  status = cryptSetAttributeString( privateKeyContext,
640  getAlgoLabel( cryptAlgo ),
641  paramStrlen( getAlgoLabel( cryptAlgo ) ) );
642  if( cryptStatusOK( status ) )
643  status = cryptGenerateKey( privateKeyContext );
644  if( cryptStatusError( status ) )
645  return( FALSE );
646  }
647  else
648  {
649  if( !loadPrivateKeyContext( &privateKeyContext, cryptAlgo ) )
650  return( FALSE );
651  }
652 
653  /* Create/open the file keyset. For the first call (with RSA) we create
654  a new keyset, for subsequent calls we update the existing keyset */
655  status = cryptKeysetOpen( &cryptKeyset, CRYPT_UNUSED, CRYPT_KEYSET_FILE,
656  useAltKeyFile ? TEST_PRIVKEY_ALT_FILE : TEST_PRIVKEY_FILE,
657  ( cryptAlgo == CRYPT_ALGO_RSA ) ? CRYPT_KEYOPT_CREATE : \
659  if( cryptStatusError( status ) )
660  {
661  cryptDestroyContext( privateKeyContext );
662  if( useAltKeyFile && status == CRYPT_ERROR_NOTAVAIL )
663  {
664  /* If the format isn't supported, this isn't a problem */
665  puts( "Write of RSA private key to alternative key file "
666  "skipped.\n" );
667  return( TRUE );
668  }
669  printf( "cryptKeysetOpen() failed with error code %d, line %d.\n",
670  status, __LINE__ );
671  return( FALSE );
672  }
673 
674  /* Write the key to the file */
675  status = cryptAddPrivateKey( cryptKeyset, privateKeyContext,
677  if( cryptStatusError( status ) )
678  {
679  printExtError( cryptKeyset, "cryptAddPrivateKey()", status,
680  __LINE__ );
681  return( FALSE );
682  }
683 
684  /* Close the keyset */
685  status = cryptKeysetClose( cryptKeyset );
686  if( cryptStatusError( status ) )
687  {
688  printf( "cryptKeysetClose() failed with error code %d, line %d.\n",
689  status, __LINE__ );
690  return( FALSE );
691  }
692 
693  /* Clean up */
694  cryptDestroyContext( privateKeyContext );
695  printf( "Write of %s private key to %skey file succeeded.\n\n",
696  getAlgoName( cryptAlgo ), useAltKeyFile ? "alternative " : "" );
697  return( TRUE );
698  }
699 
700 int testReadWriteFileKey( void )
701  {
702  if( !writeFileKey( CRYPT_ALGO_RSA, FALSE, FALSE ) )
703  return( FALSE );
704  if( !readFileKey( CRYPT_ALGO_RSA, FALSE ) )
705  return( FALSE );
706  if( !writeFileKey( CRYPT_ALGO_DSA, FALSE, FALSE ) )
707  return( FALSE );
708  if( !readFileKey( CRYPT_ALGO_DSA, FALSE ) )
709  return( FALSE );
711  !writeFileKey( CRYPT_ALGO_ELGAMAL, FALSE, FALSE ) )
712  return( FALSE );
714  !readFileKey( CRYPT_ALGO_ELGAMAL, FALSE ) )
715  return( FALSE );
717  !writeFileKey( CRYPT_ALGO_ECDSA, FALSE, FALSE ) )
718  return( FALSE );
720  !readFileKey( CRYPT_ALGO_ECDSA, FALSE ) )
721  return( FALSE );
722  return( TRUE );
723  }
724 
725 int testReadWriteAltFileKey( void )
726  {
727  if( !writeFileKey( CRYPT_ALGO_RSA, TRUE, FALSE ) )
728  return( FALSE );
729  return( readFileKey( CRYPT_ALGO_RSA, TRUE ) );
730  }
731 
732 static int fileKeyImport( const int fileNo )
733  {
734  CRYPT_KEYSET cryptKeyset;
736  BYTE buffer[ BUFFER_SIZE ];
737  int status;
738 
739  printf( "Testing PKCS #15 file #%d import...\n", fileNo );
740 
741  /* Open the file keyset */
742  filenameFromTemplate( buffer, P15_FILE_TEMPLATE, fileNo );
743  status = cryptKeysetOpen( &cryptKeyset, CRYPT_UNUSED, CRYPT_KEYSET_FILE,
744  buffer, CRYPT_KEYOPT_READONLY );
745  if( fileNo == 1 && status == CRYPT_ERROR_OVERFLOW )
746  {
747  /* Depending on the setting of MAX_PKCS15_OBJECTS this keyset may
748  contain too many keys to be read, if we get an overflow error we
749  continue normally */
750  printf( "Keyset contains too many items to read, line %d.\n (This "
751  "is an expected condition, continuing...).\n", __LINE__ );
752  return( TRUE );
753  }
754  if( fileNo == 2 && status == CRYPT_ERROR_BADDATA )
755  {
756  /* This test file is from a pre-release implementation and may not
757  necessarily be correct so we don't complain in the case of
758  errors */
759  puts( "Skipping keyset containing specil-case data values." );
760  return( TRUE );
761  }
762  if( cryptStatusError( status ) )
763  {
764  printf( "cryptKeysetOpen() failed with error code %d, line %d.\n",
765  status, __LINE__ );
766  return( FALSE );
767  }
768 
769  /* Read the key from the file */
770  if( fileNo == 1 )
771  {
772  status = cryptGetPrivateKey( cryptKeyset, &cryptContext,
773  CRYPT_KEYID_NAME, TEXT( "John Smith 0" ),
774  TEXT( "password" ) );
775  }
776  else
777  {
778  status = cryptGetPrivateKey( cryptKeyset, &cryptContext,
779  CRYPT_KEYID_NAME, TEXT( "key and chain" ),
780  TEXT( "password" ) );
781  }
782  if( cryptStatusError( status ) )
783  {
784  printExtError( cryptKeyset, "cryptGetPrivateKey()", status,
785  __LINE__ );
786  return( FALSE );
787  }
788  cryptDestroyContext( cryptContext );
789 
790  /* Close the keyset */
791  status = cryptKeysetClose( cryptKeyset );
792  if( cryptStatusError( status ) )
793  {
794  printf( "cryptKeysetClose() failed with error code %d, line %d.\n",
795  status, __LINE__ );
796  return( FALSE );
797  }
798 
799  return( TRUE );
800  }
801 
802 int testImportFileKey( void )
803  {
804 #if 0 /* Disabled until we can get valid third-party PKCS #15 test data */
805  int i;
806 
807  for( i = 1; i <= 1; i++ )
808  {
809  if( !fileKeyImport( i ) )
810  return( FALSE );
811  }
812 #endif /* 0 */
813 
814  return( TRUE );
815  }
816 
817 /* Read only the public key/certificate/certificate chain portion of a
818  keyset */
819 
820 int testReadFilePublicKey( void )
821  {
822  CRYPT_KEYSET cryptKeyset;
824  int cryptAlgo, status;
825 
826  puts( "Testing public key read from key file..." );
827 
828  /* Open the file keyset */
829  status = cryptKeysetOpen( &cryptKeyset, CRYPT_UNUSED, CRYPT_KEYSET_FILE,
830  TEST_PRIVKEY_FILE, CRYPT_KEYOPT_READONLY );
831  if( cryptStatusError( status ) )
832  {
833  printf( "cryptKeysetOpen() failed with error code %d, line %d.\n",
834  status, __LINE__ );
835  return( FALSE );
836  }
837 
838  /* Read the public key from the file and make sure that it really is a
839  public-key context */
840  status = cryptGetPublicKey( cryptKeyset, &cryptContext, CRYPT_KEYID_NAME,
842  if( cryptStatusError( status ) )
843  {
844  printExtError( cryptKeyset, "cryptGetPublicKey()", status,
845  __LINE__ );
846  return( FALSE );
847  }
848  status = cryptGetAttribute( cryptContext, CRYPT_CTXINFO_ALGO, &cryptAlgo );
849  if( cryptStatusError( status ) || \
850  cryptAlgo < CRYPT_ALGO_FIRST_PKC || cryptAlgo > CRYPT_ALGO_LAST_PKC )
851  {
852  puts( "Returned object isn't a public-key context." );
853  return( FALSE );
854  }
855 
856  /* Close the keyset */
857  status = cryptKeysetClose( cryptKeyset );
858  if( cryptStatusError( status ) )
859  {
860  printf( "cryptKeysetClose() failed with error code %d, line %d.\n",
861  status, __LINE__ );
862  return( FALSE );
863  }
864 
865  cryptDestroyContext( cryptContext );
866 
867  puts( "Read of public key from key file succeeded.\n" );
868  return( TRUE );
869  }
870 
871 static int readCert( const char *certTypeName,
872  const CRYPT_CERTTYPE_TYPE certType,
873  const BOOLEAN readPrivateKey )
874  {
875  CRYPT_KEYSET cryptKeyset;
876  int value, status;
877 
878  printf( "Testing %s read from key file...\n", certTypeName );
879 
880  /* Open the file keyset */
881  status = cryptKeysetOpen( &cryptKeyset, CRYPT_UNUSED, CRYPT_KEYSET_FILE,
882  TEST_PRIVKEY_FILE, CRYPT_KEYOPT_READONLY );
883  if( cryptStatusError( status ) )
884  {
885  printf( "cryptKeysetOpen() failed with error code %d, line %d.\n",
886  status, __LINE__ );
887  return( FALSE );
888  }
889 
890  /* Read the certificate from the file and make sure that it really is a
891  certificate */
892  if( readPrivateKey )
893  {
895 
896  status = cryptGetPrivateKey( cryptKeyset, &cryptContext,
899  if( cryptStatusError( status ) )
900  {
901  printExtError( cryptKeyset, "cryptGetPrivateKey()", status,
902  __LINE__ );
903  return( FALSE );
904  }
905  if( !checkCertPresence( cryptContext, certTypeName, certType ) )
906  return( FALSE );
907  cryptDestroyContext( cryptContext );
908  }
909  else
910  {
911  CRYPT_CERTIFICATE cryptCert;
912 
913  status = cryptGetPublicKey( cryptKeyset, &cryptCert, CRYPT_KEYID_NAME,
914  ( certType == CRYPT_CERTTYPE_CERTIFICATE ) ? \
916  if( cryptStatusError( status ) )
917  {
918  printExtError( cryptKeyset, "cryptGetPublicKey()", status,
919  __LINE__ );
920  return( FALSE );
921  }
922  status = cryptGetAttribute( cryptCert, CRYPT_CERTINFO_CERTTYPE, &value );
923  if( cryptStatusError( status ) || value != certType )
924  {
925  printf( "Returned object isn't a %s, line %d.\n", certTypeName,
926  __LINE__ );
927  return( FALSE );
928  }
929  cryptDestroyCert( cryptCert );
930  }
931 
932  /* Close the keyset */
933  status = cryptKeysetClose( cryptKeyset );
934  if( cryptStatusError( status ) )
935  {
936  printf( "cryptKeysetClose() failed with error code %d, line %d.\n",
937  status, __LINE__ );
938  return( FALSE );
939  }
940 
941  printf( "Read of %s from key file succeeded.\n\n", certTypeName );
942  return( TRUE );
943  }
944 
945 int testReadFileCert( void )
946  {
947  return( readCert( "certificate", CRYPT_CERTTYPE_CERTIFICATE, FALSE ) );
948  }
949 int testReadFileCertPrivkey( void )
950  {
951  return( readCert( "private key with certificate", CRYPT_CERTTYPE_CERTIFICATE, TRUE ) );
952  }
953 int testReadFileCertChain( void )
954  {
955  return( readCert( "certificate chain", CRYPT_CERTTYPE_CERTCHAIN, FALSE ) );
956  }
957 
958 /* Test the ability to detect key data corruption/modification */
959 
960 int testReadCorruptedKey( void )
961  {
962  CRYPT_KEYSET cryptKeyset;
964  int i, status;
965 
966  puts( "Testing detection of key corruption in key file..." );
967  for( i = 0; i < 4; i++ )
968  {
969  /* Copy the file to a temporary one, corrupting a data byte in the
970  process */
971  status = copyModifiedFile( TEST_PRIVKEY_FILE, TEST_PRIVKEY_TMP_FILE,
972  256 );
973  if( !status )
974  {
975  printf( "Couldn't copy keyset to temporary file, line %d.\n",
976  __LINE__ );
977  return( FALSE );
978  }
979 
980  /* Try and read the key. The open should succeed, the read should
981  fail */
982  status = cryptKeysetOpen( &cryptKeyset, CRYPT_UNUSED,
985  if( cryptStatusError( status ) )
986  {
987  printf( "cryptKeysetOpen() failed with error code %d, line %d.\n",
988  status, __LINE__ );
989  return( FALSE );
990  }
991  status = cryptGetPrivateKey( cryptKeyset, &cryptContext,
994  if( cryptStatusOK( status ) )
995  {
996  cryptDestroyContext( cryptContext );
997  printf( "Read of corrupted key succeeded when it should have "
998  "failed, line %d.\n", __LINE__ );
999  return( FALSE );
1000  }
1001  cryptKeysetClose( cryptKeyset );
1002  }
1003  puts( "Detection of key corruption succeeded.\n" );
1004 
1005  return( TRUE );
1006  }
1007 
1008 /****************************************************************************
1009 * *
1010 * Certificate Read/Write Tests *
1011 * *
1012 ****************************************************************************/
1013 
1014 /* Update a keyset to contain a certificate */
1015 
1016 int testAddTrustedCert( void )
1017  {
1018  CRYPT_KEYSET cryptKeyset;
1019  CRYPT_CERTIFICATE trustedCert;
1020  int value, status;
1021 
1022  puts( "Testing trusted certificate add to key file..." );
1023 
1024  /* Read the CA root certificate. We have to make it explicitly non-
1025  trusted since something else may have made it trusted previously */
1026  status = importCertFromTemplate( &trustedCert, CERT_FILE_TEMPLATE, 1 );
1027  if( cryptStatusError( status ) )
1028  {
1029  puts( "Couldn't read certificate from file, skipping test of trusted "
1030  "certificate write..." );
1031  return( TRUE );
1032  }
1034  &value );
1035  if( value )
1037  FALSE );
1038 
1039  /* Open the keyset, update it with the trusted certificate, and close it.
1040  Before we make the certificate trusted, we try adding it as a standard
1041  certificate, which should fail */
1042  status = cryptKeysetOpen( &cryptKeyset, CRYPT_UNUSED, CRYPT_KEYSET_FILE,
1043  TEST_PRIVKEY_FILE, CRYPT_KEYOPT_CREATE );
1044  if( cryptStatusError( status ) )
1045  {
1046  printf( "cryptKeysetOpen() failed with error code %d, line %d.\n",
1047  status, __LINE__ );
1048  return( FALSE );
1049  }
1050  status = cryptAddPublicKey( cryptKeyset, trustedCert );
1051  if( cryptStatusOK( status ) )
1052  {
1053  printf( "cryptAddPublicKey() of non-trusted certificate succeeded "
1054  "when it should have failed, line %d.\n", __LINE__ );
1055  return( FALSE );
1056  }
1058  status = cryptAddPublicKey( cryptKeyset, trustedCert );
1059  if( cryptStatusError( status ) )
1060  {
1061  printExtError( cryptKeyset, "cryptAddPublicKey()", status,
1062  __LINE__ );
1063  return( FALSE );
1064  }
1065  cryptSetAttribute( trustedCert, CRYPT_CERTINFO_TRUSTED_IMPLICIT, value );
1066  cryptDestroyCert( trustedCert );
1067  status = cryptKeysetClose( cryptKeyset );
1068  if( cryptStatusError( status ) )
1069  {
1070  printf( "cryptKeysetClose() failed with error code %d, line %d.\n",
1071  status, __LINE__ );
1072  return( FALSE );
1073  }
1074 
1075  puts( "Trusted certificate add to key file succeeded.\n" );
1076  return( TRUE );
1077  }
1078 
1079 int testAddGloballyTrustedCert( void )
1080  {
1081  CRYPT_CERTIFICATE trustedCert;
1082  int status;
1083 
1084  puts( "Testing globally trusted certificate add..." );
1085 
1086  /* Read the CA root certificate and make it trusted */
1087  status = importCertFromTemplate( &trustedCert, CERT_FILE_TEMPLATE, 1 );
1088  if( cryptStatusError( status ) )
1089  {
1090  puts( "Couldn't read certificate from file, skipping test of trusted "
1091  "certificate write..." );
1092  return( TRUE );
1093  }
1095 
1096  /* Update the config file with the globally trusted certificate */
1098  FALSE );
1099  if( cryptStatusError( status ) )
1100  {
1101  printf( "Globally trusted certificate add failed with error code "
1102  "%d, line %d.\n", status, __LINE__ );
1103  return( FALSE );
1104  }
1105 
1106  /* Make the certificate untrusted and update the config again */
1109  FALSE );
1110  if( cryptStatusError( status ) )
1111  {
1112  printf( "Globally trusted certificate delete failed with error code "
1113  "%d, line %d.\n", status, __LINE__ );
1114  return( FALSE );
1115  }
1116 
1117  puts( "Globally trusted certificate add succeeded.\n" );
1118  return( TRUE );
1119  }
1120 
1121 static const CERT_DATA FAR_BSS cACertData[] = {
1122  /* Identification information. Note the non-heirarchical order of the
1123  components to test the automatic arranging of the DN */
1124  { CRYPT_CERTINFO_ORGANIZATIONNAME, IS_STRING, 0, TEXT( "Dave's Wetaburgers and CA" ) },
1125  { CRYPT_CERTINFO_COMMONNAME, IS_STRING, 0, TEXT( "Dave Himself" ) },
1126  { CRYPT_CERTINFO_ORGANIZATIONALUNITNAME, IS_STRING, 0, TEXT( "Certification Division" ) },
1127  { CRYPT_CERTINFO_COUNTRYNAME, IS_STRING, 0, TEXT( "NZ" ) },
1128 
1129  /* Self-signed X.509v3 certificate */
1131 
1132  /* CA key usage */
1136 
1138  };
1139 
1140 int testUpdateFileCert( void )
1141  {
1142  CRYPT_KEYSET cryptKeyset;
1143  CRYPT_CERTIFICATE cryptCert;
1144  CRYPT_CONTEXT publicKeyContext, privateKeyContext;
1145  int status;
1146 
1147  puts( "Testing certificate update to key file ..." );
1148 
1149  /* Create a self-signed CA certificate using the in-memory key (which is
1150  the same as the one in the keyset) */
1151  if( !loadRSAContexts( CRYPT_UNUSED, &publicKeyContext, &privateKeyContext ) )
1152  return( FALSE );
1153  status = cryptCreateCert( &cryptCert, CRYPT_UNUSED,
1155  if( cryptStatusError( status ) )
1156  {
1157  printf( "cryptCreateCert() failed with error code %d, line %d.\n",
1158  status, __LINE__ );
1159  return( FALSE );
1160  }
1161  status = cryptSetAttribute( cryptCert,
1162  CRYPT_CERTINFO_SUBJECTPUBLICKEYINFO, publicKeyContext );
1163  if( cryptStatusOK( status ) && \
1164  !addCertFields( cryptCert, cACertData, __LINE__ ) )
1165  return( FALSE );
1166  if( cryptStatusOK( status ) )
1167  status = cryptSignCert( cryptCert, privateKeyContext );
1168  destroyContexts( CRYPT_UNUSED, publicKeyContext, privateKeyContext );
1169  if( cryptStatusError( status ) )
1170  {
1171  printf( "Certificate creation failed with error code %d, "
1172  "line %d.\n", status, __LINE__ );
1173  cryptDestroyCert( status );
1174  return( FALSE );
1175  }
1176 
1177  /* Open the keyset, update it with the certificate, and close it */
1178  status = cryptKeysetOpen( &cryptKeyset, CRYPT_UNUSED, CRYPT_KEYSET_FILE,
1179  TEST_PRIVKEY_FILE, CRYPT_KEYOPT_NONE );
1180  if( cryptStatusError( status ) )
1181  {
1182  printf( "cryptKeysetOpen() failed with error code %d, line %d.\n",
1183  status, __LINE__ );
1184  return( FALSE );
1185  }
1186  status = cryptAddPublicKey( cryptKeyset, cryptCert );
1187  if( cryptStatusError( status ) )
1188  {
1189  printExtError( cryptKeyset, "cryptAddPublicKey()", status,
1190  __LINE__ );
1191  return( FALSE );
1192  }
1193  cryptDestroyCert( cryptCert );
1194  status = cryptKeysetClose( cryptKeyset );
1195  if( cryptStatusError( status ) )
1196  {
1197  printf( "cryptKeysetClose() failed with error code %d, line %d.\n",
1198  status, __LINE__ );
1199  return( FALSE );
1200  }
1201 
1202  puts( "Certificate update to key file succeeded.\n" );
1203  return( TRUE );
1204  }
1205 
1206 /* Update a keyset to contain a certificate chain */
1207 
1208 static int writeFileCertChain( const CERT_DATA *certRequestData,
1209  const C_STR keyFileName,
1210  const C_STR certFileName,
1211  const BOOLEAN isTestRun,
1212  const BOOLEAN writeLongChain,
1213  const CRYPT_ALGO_TYPE cryptAlgo,
1214  const int keySize )
1215  {
1216  CRYPT_KEYSET cryptKeyset;
1217  CRYPT_CERTIFICATE cryptCertChain;
1218  CRYPT_CONTEXT cryptCAKey, cryptKey;
1219  int status;
1220 
1221  if( isTestRun )
1222  {
1223  printf( "Testing %scert chain write to key file ...\n",
1224  writeLongChain ? "long " : "" );
1225  }
1226 
1227  /* Generate a key to certify. We can't just reuse the built-in test key
1228  because this has already been used as the CA key and the keyset code
1229  won't allow it to be added to a keyset as both a CA key and user key,
1230  so we have to generate a new one */
1231  status = cryptCreateContext( &cryptKey, CRYPT_UNUSED, cryptAlgo );
1232  if( cryptStatusOK( status ) && keySize != CRYPT_USE_DEFAULT )
1233  status = cryptSetAttribute( cryptKey, CRYPT_CTXINFO_KEYSIZE,
1234  keySize );
1235  if( cryptStatusOK( status ) )
1236  {
1237  status = cryptSetAttributeString( cryptKey, CRYPT_CTXINFO_LABEL,
1240  }
1241  if( cryptStatusOK( status ) )
1242  status = cryptGenerateKey( cryptKey );
1243  if( cryptStatusError( status ) )
1244  {
1245  printf( "Test key generation failed with error code %d, line %d.\n",
1246  status, __LINE__ );
1247  return( FALSE );
1248  }
1249 
1250  /* Get the CA's key. The length of the chain is determined by the
1251  number of certs attached to the CAs certificate, so handling long vs.
1252  short chains is pretty simple */
1253  if( writeLongChain )
1254  status = getPrivateKey( &cryptCAKey, ICA_PRIVKEY_FILE,
1256  else
1257  status = getPrivateKey( &cryptCAKey, CA_PRIVKEY_FILE,
1259  if( cryptStatusError( status ) )
1260  {
1261  printf( "CA private key read failed with error code %d, line %d.\n",
1262  status, __LINE__ );
1263  return( FALSE );
1264  }
1265 
1266  /* Create the keyset and add the private key to it */
1267  status = cryptKeysetOpen( &cryptKeyset, CRYPT_UNUSED, CRYPT_KEYSET_FILE,
1268  keyFileName, CRYPT_KEYOPT_CREATE );
1269  if( cryptStatusError( status ) )
1270  {
1271  printf( "cryptKeysetOpen() failed with error code %d, line %d.\n",
1272  status, __LINE__ );
1273  return( FALSE );
1274  }
1275  status = cryptAddPrivateKey( cryptKeyset, cryptKey,
1277  if( cryptStatusError( status ) )
1278  {
1279  printExtError( cryptKeyset, "cryptAddPrivateKey()", status,
1280  __LINE__ );
1281  return( FALSE );
1282  }
1283 
1284  /* Create the certificate chain for the new key */
1285  status = cryptCreateCert( &cryptCertChain, CRYPT_UNUSED,
1287  if( cryptStatusOK( status ) )
1288  status = cryptSetAttribute( cryptCertChain,
1290  cryptDestroyContext( cryptKey );
1291  if( cryptStatusOK( status ) && \
1292  !addCertFields( cryptCertChain, certRequestData, __LINE__ ) )
1293  return( FALSE );
1294 #ifndef _WIN32_WCE /* Windows CE doesn't support ANSI C time functions */
1295  if( cryptStatusOK( status ) && !isTestRun )
1296  {
1297  const time_t validity = time( NULL ) + ( 86400L * 365 * 3 );
1298 
1299  /* Make it valid for 5 years instead of 1 to avoid problems when
1300  users run the self-test with very old copies of the code */
1301  status = cryptSetAttributeString( cryptCertChain,
1302  CRYPT_CERTINFO_VALIDTO, &validity, sizeof( time_t ) );
1303  }
1304 #endif /* WinCE */
1305  if( cryptStatusOK( status ) )
1306  status = cryptSignCert( cryptCertChain, cryptCAKey );
1307  cryptDestroyContext( cryptCAKey );
1308  if( cryptStatusError( status ) )
1309  {
1310  printf( "Certificate chain creation failed with error code %d, "
1311  "line %d.\n", status, __LINE__ );
1312  printErrorAttributeInfo( cryptCertChain );
1313  return( FALSE );
1314  }
1315 
1316  /* Add the certificate chain to the file */
1317  status = cryptAddPublicKey( cryptKeyset, cryptCertChain );
1318  if( cryptStatusError( status ) )
1319  {
1320  printExtError( cryptKeyset, "cryptAddPrivateKey()", status,
1321  __LINE__ );
1322  return( FALSE );
1323  }
1324  if( certFileName != NULL )
1325  {
1326  FILE *filePtr;
1328  int length;
1329 
1330  /* Save the certificate to disk for use in request/response
1331  protocols */
1332  status = cryptExportCert( certBuffer, BUFFER_SIZE, &length,
1334  cryptCertChain );
1335  if( cryptStatusError( status ) )
1336  {
1337  printf( "cryptExportCert() failed with error code %d, "
1338  "line %d.\n", status, __LINE__ );
1339  return( FALSE );
1340  }
1341  if( ( filePtr = fopen( convertFileName( certFileName ), \
1342  "wb" ) ) != NULL )
1343  {
1344  int count;
1345 
1346  count = fwrite( certBuffer, 1, length, filePtr );
1347  fclose( filePtr );
1348  if( count < length )
1349  {
1350  remove( convertFileName( certFileName ) );
1351  puts( "Warning: Couldn't save certificate chain to disk, "
1352  "this will cause later\n tests to fail. "
1353  "Press a key to continue." );
1354  getchar();
1355  }
1356  }
1357  }
1358  cryptDestroyCert( cryptCertChain );
1359  status = cryptKeysetClose( cryptKeyset );
1360  if( cryptStatusError( status ) )
1361  {
1362  printf( "cryptKeysetClose() failed with error code %d, line %d.\n",
1363  status, __LINE__ );
1364  return( FALSE );
1365  }
1366 
1367  if( isTestRun )
1368  puts( "Certificate chain write to key file succeeded.\n" );
1369  return( TRUE );
1370  }
1371 
1372 static const CERT_DATA FAR_BSS certRequestData[] = {
1373  /* Identification information */
1374  { CRYPT_CERTINFO_COUNTRYNAME, IS_STRING, 0, TEXT( "NZ" ) },
1375  { CRYPT_CERTINFO_ORGANIZATIONNAME, IS_STRING, 0, TEXT( "Dave's Wetaburgers" ) },
1376  { CRYPT_CERTINFO_ORGANIZATIONALUNITNAME, IS_STRING, 0, TEXT( "Procurement" ) },
1377  { CRYPT_CERTINFO_COMMONNAME, IS_STRING, 0, TEXT( "Dave Smith" ) },
1379  { CRYPT_ATTRIBUTE_CURRENT, IS_NUMERIC, CRYPT_CERTINFO_SUBJECTNAME }, /* Re-select subject DN */
1380 
1381  { CRYPT_ATTRIBUTE_NONE, 0, 0, NULL }
1382  };
1383 
1384 int testWriteFileCertChain( void )
1385  {
1386  return( writeFileCertChain( certRequestData, TEST_PRIVKEY_FILE, NULL,
1388  CRYPT_USE_DEFAULT ) );
1389  }
1390 
1391 int testWriteFileLongCertChain( void )
1392  {
1393  return( writeFileCertChain( certRequestData, TEST_PRIVKEY_FILE, NULL,
1395  CRYPT_USE_DEFAULT ) );
1396  }
1397 
1398 /* Delete a key from a file */
1399 
1400 int testDeleteFileKey( void )
1401  {
1402  CRYPT_KEYSET cryptKeyset;
1404  int status;
1405 
1406  puts( "Testing delete from key file..." );
1407 
1408  /* Open the file keyset */
1409  status = cryptKeysetOpen( &cryptKeyset, CRYPT_UNUSED, CRYPT_KEYSET_FILE,
1410  TEST_PRIVKEY_FILE, CRYPT_KEYOPT_NONE );
1411  if( cryptStatusError( status ) )
1412  {
1413  printf( "cryptKeysetOpen() failed with error code %d, line %d.\n",
1414  status, __LINE__ );
1415  return( FALSE );
1416  }
1417 
1418  /* Delete the key from the file. Since we don't need the DSA key any
1419  more we use it as the key to delete */
1420  status = cryptDeleteKey( cryptKeyset, CRYPT_KEYID_NAME,
1422  if( cryptStatusError( status ) )
1423  {
1424  printExtError( cryptKeyset, "cryptDeletePrivateKey()", status,
1425  __LINE__ );
1426  return( FALSE );
1427  }
1428  status = cryptGetPublicKey( cryptKeyset, &cryptContext, CRYPT_KEYID_NAME,
1430  if( cryptStatusOK( status ) )
1431  {
1432  cryptDestroyContext( cryptContext );
1433  puts( "cryptDeleteKey() claimed the key was deleted but it's still "
1434  "present." );
1435  return( FALSE );
1436  }
1437 
1438  /* Close the keyset */
1439  status = cryptKeysetClose( cryptKeyset );
1440  if( cryptStatusError( status ) )
1441  {
1442  printf( "cryptKeysetClose() failed with error code %d, line %d.\n",
1443  status, __LINE__ );
1444  return( FALSE );
1445  }
1446 
1447  puts( "Delete from key file succeeded.\n" );
1448  return( TRUE );
1449  }
1450 
1451 /* Change the password for a key in a file */
1452 
1453 int testChangeFileKeyPassword( void )
1454  {
1455  CRYPT_KEYSET cryptKeyset;
1457  int status;
1458 
1459  puts( "Testing change of key password for key file..." );
1460 
1461  /* Open the file keyset */
1462  status = cryptKeysetOpen( &cryptKeyset, CRYPT_UNUSED, CRYPT_KEYSET_FILE,
1463  TEST_PRIVKEY_FILE, CRYPT_KEYOPT_NONE );
1464  if( cryptStatusError( status ) )
1465  {
1466  printf( "cryptKeysetOpen() failed with error code %d, line %d.\n",
1467  status, __LINE__ );
1468  return( FALSE );
1469  }
1470 
1471  /* Read the key using the old password, delete it, and write it back
1472  using the new password. To keep things simple we just use the same
1473  password (since the key will be used again later), the test of the
1474  delete function earlier on has already confirmed that the old key
1475  and password will be deleted so there's no chance of a false positive */
1476  status = cryptGetPrivateKey( cryptKeyset, &cryptContext,
1479  if( cryptStatusOK( status ) )
1480  status = cryptDeleteKey( cryptKeyset, CRYPT_KEYID_NAME,
1482  if( cryptStatusOK( status ) )
1483  status = cryptAddPrivateKey( cryptKeyset, cryptContext,
1485  if( cryptStatusError( status ) )
1486  {
1487  printExtError( cryptKeyset, "password change", status,
1488  __LINE__ );
1489  return( FALSE );
1490  }
1491  cryptDestroyContext( cryptContext );
1492 
1493  /* Close the keyset */
1494  status = cryptKeysetClose( cryptKeyset );
1495  if( cryptStatusError( status ) )
1496  {
1497  printf( "cryptKeysetClose() failed with error code %d, line %d.\n",
1498  status, __LINE__ );
1499  return( FALSE );
1500  }
1501 
1502  puts( "Password change for key in key file succeeded.\n" );
1503  return( TRUE );
1504  }
1505 
1506 /* Write a key and certificate to a file in a single operation */
1507 
1508 static int writeSingleStepFileCert( const CRYPT_ALGO_TYPE cryptAlgo,
1509  const BOOLEAN useAltKeyFile )
1510  {
1511  CRYPT_KEYSET cryptKeyset;
1512  CRYPT_CERTIFICATE cryptCert;
1514  int status;
1515 
1516  printf( "Testing single-step %s key+certificate write to %skey file...\n",
1517  getAlgoName( cryptAlgo ), useAltKeyFile ? "alternative " : "" );
1518 
1519  /* Create a self-signed CA certificate */
1520  if( !loadPrivateKeyContext( &cryptContext, cryptAlgo ) )
1521  return( FALSE );
1522  status = cryptCreateCert( &cryptCert, CRYPT_UNUSED,
1524  if( cryptStatusError( status ) )
1525  {
1526  printf( "cryptCreateCert() failed with error code %d, line %d.\n",
1527  status, __LINE__ );
1528  return( FALSE );
1529  }
1530  status = cryptSetAttribute( cryptCert,
1531  CRYPT_CERTINFO_SUBJECTPUBLICKEYINFO, cryptContext );
1532  if( cryptStatusOK( status ) && \
1533  !addCertFields( cryptCert, cACertData, __LINE__ ) )
1534  return( FALSE );
1535  if( cryptStatusOK( status ) )
1536  status = cryptSignCert( cryptCert, cryptContext );
1537  if( cryptStatusError( status ) )
1538  {
1539  printf( "Certificate creation failed with error code %d, "
1540  "line %d.\n", status, __LINE__ );
1541  cryptDestroyCert( status );
1542  return( FALSE );
1543  }
1544 
1545  /* Open the keyset, write the key and certificate, and close it */
1546  status = cryptKeysetOpen( &cryptKeyset, CRYPT_UNUSED, CRYPT_KEYSET_FILE,
1547  useAltKeyFile ? TEST_PRIVKEY_ALT_FILE : TEST_PRIVKEY_FILE,
1549  if( cryptStatusError( status ) )
1550  {
1551  cryptDestroyContext( cryptContext );
1552  cryptDestroyCert( cryptCert );
1553  if( useAltKeyFile && status == CRYPT_ERROR_NOTAVAIL )
1554  {
1555  /* If the format isn't supported, this isn't a problem */
1556  puts( "Single-step update to alternative key file skipped.\n" );
1557  return( TRUE );
1558  }
1559  printf( "cryptKeysetOpen() failed with error code %d, line %d.\n",
1560  status, __LINE__ );
1561  return( FALSE );
1562  }
1563  status = cryptAddPrivateKey( cryptKeyset, cryptContext,
1565  if( cryptStatusError( status ) )
1566  {
1567  printExtError( cryptKeyset, "cryptAddPrivateKey()", status,
1568  __LINE__ );
1569  return( FALSE );
1570  }
1571  status = cryptAddPublicKey( cryptKeyset, cryptCert );
1572  if( cryptStatusError( status ) )
1573  {
1574  printExtError( cryptKeyset, "cryptAddPrivateKey()", status,
1575  __LINE__ );
1576  return( FALSE );
1577  }
1578  cryptDestroyContext( cryptContext );
1579  cryptDestroyCert( cryptCert );
1580 
1581  /* Try and read the key+certificate back before we close the keyset.
1582  This ensures that the in-memory data has been updated correctly */
1583  status = cryptGetPrivateKey( cryptKeyset, &cryptContext,
1584  CRYPT_KEYID_NAME, getAlgoLabel( cryptAlgo ),
1586  cryptDestroyContext( cryptContext );
1587  if( cryptStatusError( status ) )
1588  {
1589  cryptKeysetClose( cryptKeyset );
1590  printExtError( cryptKeyset,
1591  "private key read from in-memory cached keyset data",
1592  status, __LINE__ );
1593  return( FALSE );
1594  }
1595 
1596  /* Close the keyset, which flushes the in-memory changes to disk. The
1597  cacheing of data in memory ensures that all keyset updates are atomic,
1598  so that it's nearly impossible to corrupt a private key keyset during
1599  an update */
1600  status = cryptKeysetClose( cryptKeyset );
1601  if( cryptStatusError( status ) )
1602  {
1603  printf( "cryptKeysetClose() failed with error code %d, line %d.\n",
1604  status, __LINE__ );
1605  return( FALSE );
1606  }
1607 
1608  /* Try and read the key+certificate back from disk rather than the
1609  cached, in-memory version */
1610  status = getPrivateKey( &cryptContext,
1611  useAltKeyFile ? TEST_PRIVKEY_ALT_FILE : TEST_PRIVKEY_FILE,
1612  getAlgoLabel( cryptAlgo ), TEST_PRIVKEY_PASSWORD );
1613  cryptDestroyContext( cryptContext );
1614  if( cryptStatusError( status ) )
1615  {
1616  printExtError( cryptKeyset,
1617  "private key read from on-disk keyset data",
1618  status, __LINE__ );
1619  return( FALSE );
1620  }
1621 
1622  printf( "Single-step %s key+certificate write to %skey file succeeded.\n\n",
1623  getAlgoName( cryptAlgo ), useAltKeyFile ? "alternative " : "" );
1624  return( TRUE );
1625  }
1626 
1627 int testSingleStepFileCert( void )
1628  {
1629  if( !writeSingleStepFileCert( CRYPT_ALGO_RSA, FALSE ) )
1630  return( FALSE );
1631  if( !writeSingleStepFileCert( CRYPT_ALGO_DSA, FALSE ) )
1632  return( FALSE );
1634  !writeSingleStepFileCert( CRYPT_ALGO_ECDSA, FALSE ) )
1635  return( FALSE );
1636  return( TRUE );
1637  }
1638 
1639 int testSingleStepAltFileCert( void )
1640  {
1641  return( writeSingleStepFileCert( CRYPT_ALGO_RSA, TRUE ) );
1642  }
1643 
1644 /* Write two keys and certs (signature + encryption) with the same DN to a
1645  file */
1646 
1647 int testDoubleCertFile( void )
1648  {
1649  CRYPT_KEYSET cryptKeyset;
1650  CRYPT_CERTIFICATE cryptSigCert, cryptEncryptCert;
1651  CRYPT_CONTEXT cryptCAKey, cryptSigContext, cryptEncryptContext;
1652  int status;
1653 
1654  puts( "Testing separate signature+encryption certificate write to key "
1655  "file..." );
1656  doubleCertOK = FALSE;
1657 
1658  /* Get the CA's key */
1659  status = getPrivateKey( &cryptCAKey, CA_PRIVKEY_FILE,
1661  if( cryptStatusError( status ) )
1662  {
1663  printf( "CA private key read failed with error code %d, line %d.\n",
1664  status, __LINE__ );
1665  return( FALSE );
1666  }
1667 
1668  /* Generate two keys to certify. We can't just use the built-in test key
1669  because cryptlib will detect it being added to the keyset a second time
1670  (if we reuse it for both keys) and because the label is a generic one
1671  that doesn't work if there are two keys */
1672  status = cryptCreateContext( &cryptSigContext, CRYPT_UNUSED,
1673  CRYPT_ALGO_RSA );
1674  if( cryptStatusOK( status ) )
1675  {
1676  status = cryptSetAttributeString( cryptSigContext,
1679  }
1680  if( cryptStatusOK( status ) )
1681  status = cryptGenerateKey( cryptSigContext );
1682  if( cryptStatusError( status ) )
1683  {
1684  printf( "Test key generation failed with error code %d, line %d.\n",
1685  status, __LINE__ );
1686  return( FALSE );
1687  }
1688  status = cryptCreateContext( &cryptEncryptContext, CRYPT_UNUSED,
1689  CRYPT_ALGO_RSA );
1690  if( cryptStatusOK( status ) )
1691  status = cryptSetAttributeString( cryptEncryptContext,
1694  if( cryptStatusOK( status ) )
1695  status = cryptGenerateKey( cryptEncryptContext );
1696  if( cryptStatusError( status ) )
1697  {
1698  printf( "Test key generation failed with error code %d, line %d.\n",
1699  status, __LINE__ );
1700  return( FALSE );
1701  }
1702 
1703  /* Create the certs containing the keys. In order to avoid clashes with
1704  other keys with the same CN in the public-key database, we give the
1705  certs abnormal CNs. This isn't necessary for cryptlib to manage them,
1706  but because later code tries to delete leftover certs from previous
1707  runs with the generic name used in the self-tests, which would also
1708  delete these certs */
1709  status = cryptCreateCert( &cryptSigCert, CRYPT_UNUSED,
1711  if( cryptStatusOK( status ) )
1712  status = cryptSetAttribute( cryptSigCert,
1713  CRYPT_CERTINFO_SUBJECTPUBLICKEYINFO, cryptSigContext );
1714  if( cryptStatusOK( status ) && \
1715  !addCertFields( cryptSigCert, certRequestData, __LINE__ ) )
1716  return( FALSE );
1717  if( cryptStatusOK( status ) )
1718  {
1719  status = cryptDeleteAttribute( cryptSigCert,
1721  if( cryptStatusOK( status ) )
1722  {
1723  status = cryptSetAttributeString( cryptSigCert,
1724  CRYPT_CERTINFO_COMMONNAME, TEXT( "Dave Smith (Dual)" ),
1725  paramStrlen( TEXT( "Dave Smith (Dual)" ) ) );
1726  }
1727  }
1728  if( cryptStatusOK( status ) )
1729  status = cryptSetAttribute( cryptSigCert,
1731  if( cryptStatusOK( status ) )
1732  status = cryptSignCert( cryptSigCert, cryptCAKey );
1733  if( cryptStatusError( status ) )
1734  {
1735  printf( "Signature certificate creation failed with error code %d, "
1736  "line %d.\n", status, __LINE__ );
1737  printErrorAttributeInfo( cryptSigCert );
1738  return( FALSE );
1739  }
1740  status = cryptCreateCert( &cryptEncryptCert, CRYPT_UNUSED,
1742  if( cryptStatusOK( status ) )
1743  status = cryptSetAttribute( cryptEncryptCert,
1744  CRYPT_CERTINFO_SUBJECTPUBLICKEYINFO, cryptEncryptContext );
1745  if( cryptStatusOK( status ) && \
1746  !addCertFields( cryptEncryptCert, certRequestData, __LINE__ ) )
1747  return( FALSE );
1748  if( cryptStatusOK( status ) )
1749  {
1750  status = cryptDeleteAttribute( cryptEncryptCert,
1752  if( cryptStatusOK( status ) )
1753  {
1754  status = cryptSetAttributeString( cryptEncryptCert,
1755  CRYPT_CERTINFO_COMMONNAME, TEXT( "Dave Smith (Dual)" ),
1756  paramStrlen( TEXT( "Dave Smith (Dual)" ) ) );
1757  }
1758  }
1759  if( cryptStatusOK( status ) )
1760  status = cryptSetAttribute( cryptEncryptCert,
1762  if( cryptStatusOK( status ) )
1763  status = cryptSignCert( cryptEncryptCert, cryptCAKey );
1764  if( cryptStatusError( status ) )
1765  {
1766  printf( "Encryption certificate creation failed with error code %d, "
1767  "line %d.\n", status, __LINE__ );
1768  printErrorAttributeInfo( cryptEncryptCert );
1769  return( FALSE );
1770  }
1771  cryptDestroyContext( cryptCAKey );
1772 
1773  /* Open the keyset, write the keys and certificates, and close it */
1774  status = cryptKeysetOpen( &cryptKeyset, CRYPT_UNUSED, CRYPT_KEYSET_FILE,
1776  if( cryptStatusError( status ) )
1777  {
1778  printf( "cryptKeysetOpen() failed with error code %d, line %d.\n",
1779  status, __LINE__ );
1780  return( FALSE );
1781  }
1782  status = cryptAddPrivateKey( cryptKeyset, cryptSigContext,
1784  if( cryptStatusOK( status ) )
1785  status = cryptAddPrivateKey( cryptKeyset, cryptEncryptContext,
1787  if( cryptStatusError( status ) )
1788  {
1789  printExtError( cryptKeyset, "cryptAddPrivateKey()", status,
1790  __LINE__ );
1791  return( FALSE );
1792  }
1793  status = cryptAddPublicKey( cryptKeyset, cryptSigCert );
1794  if( cryptStatusOK( status ) )
1795  status = cryptAddPublicKey( cryptKeyset, cryptEncryptCert );
1796  if( cryptStatusError( status ) )
1797  {
1798  printExtError( cryptKeyset, "cryptAddPublicKey()", status,
1799  __LINE__ );
1800  return( FALSE );
1801  }
1802  status = cryptKeysetClose( cryptKeyset );
1803  if( cryptStatusError( status ) )
1804  {
1805  printf( "cryptKeysetClose() failed with error code %d, line %d.\n",
1806  status, __LINE__ );
1807  return( FALSE );
1808  }
1809 
1810  /* Write the two certs to a public-key database if there's one available
1811  (because it may not be present, we fail quietly if access to this
1812  keyset type isn't available or the keyset isn't present, it'll be
1813  picked up later by other tests).
1814 
1815  This certificate write is needed later to test the encryption vs.
1816  signature certificate handling. Since they may have been added
1817  earlier we try and delete them first (we can't use the existing
1818  version since the issuerAndSerialNumber won't match the ones in the
1819  private-key keyset) */
1820  status = cryptKeysetOpen( &cryptKeyset, CRYPT_UNUSED,
1823  if( status != CRYPT_ERROR_PARAM3 && status != CRYPT_ERROR_OPEN )
1824  {
1825  C_CHR name[ CRYPT_MAX_TEXTSIZE + 1 ];
1826  int length;
1827 
1828  if( cryptStatusError( status ) )
1829  {
1830  printf( "cryptKeysetOpen() failed with error code %d, line %d.\n",
1831  status, __LINE__ );
1832  if( status == CRYPT_ERROR_OPEN )
1833  return( CRYPT_ERROR_FAILED );
1834  return( FALSE );
1835  }
1837  name, &length );
1838 #ifdef UNICODE_STRINGS
1839  length /= sizeof( wchar_t );
1840 #endif /* UNICODE_STRINGS */
1841  name[ length ] = TEXT( '\0' );
1842  do
1843  status = cryptDeleteKey( cryptKeyset, CRYPT_KEYID_NAME, name );
1844  while( cryptStatusOK( status ) );
1845  if( status != CRYPT_ERROR_NOTFOUND )
1846  {
1847  /* Deletion of the existing keys failed for some reason, we can't
1848  continue */
1849  return( extErrorExit( cryptKeyset, "cryptDeleteKey()",
1850  status, __LINE__ ) );
1851  }
1852  status = cryptAddPublicKey( cryptKeyset, cryptSigCert );
1853  if( status != CRYPT_ERROR_NOTFOUND )
1854  {
1855  /* We can get a notfound if a database keyset is defined but
1856  hasn't been initialised yet so the necessary tables don't
1857  exist, it can be opened but an attempt to add a key will
1858  return a not found error since it's the table itself rather
1859  than any item within it that isn't being found */
1860  if( cryptStatusOK( status ) )
1861  status = cryptAddPublicKey( cryptKeyset, cryptEncryptCert );
1862  if( cryptStatusError( status ) )
1863  return( extErrorExit( cryptKeyset, "cryptAddPublicKey()",
1864  status, __LINE__ ) );
1865 
1866  /* The double-certificate keyset is set up, remember this for
1867  later tests */
1868  doubleCertOK = TRUE;
1869  }
1870  cryptKeysetClose( cryptKeyset );
1871  }
1872 
1873  /* Clean up */
1874  cryptDestroyContext( cryptSigContext );
1875  cryptDestroyContext( cryptEncryptContext );
1876  cryptDestroyCert( cryptSigCert );
1877  cryptDestroyCert( cryptEncryptCert );
1878 
1879  /* Try and read the keys+certs back */
1880  status = getPrivateKey( &cryptSigContext, DUAL_PRIVKEY_FILE,
1882  cryptDestroyContext( cryptSigContext );
1883  if( cryptStatusOK( status ) )
1884  {
1885  status = getPrivateKey( &cryptEncryptContext, DUAL_PRIVKEY_FILE,
1887  cryptDestroyContext( cryptEncryptContext );
1888  }
1889  if( cryptStatusError( status ) )
1890  {
1891  printExtError( cryptKeyset, "cryptGetPrivateKey()", status,
1892  __LINE__ );
1893  return( FALSE );
1894  }
1895 
1896  puts( "Separate signature+encryption certificate write to key file "
1897  "succeeded.\n" );
1898  return( TRUE );
1899  }
1900 
1901 /* Write a key and two certs of different validity periods to a file */
1902 
1903 #ifndef _WIN32_WCE /* Windows CE doesn't support ANSI C time functions */
1904 
1905 int testRenewedCertFile( void )
1906  {
1907  CRYPT_KEYSET cryptKeyset;
1908  CRYPT_CERTIFICATE cryptOldCert, cryptNewCert;
1909  CRYPT_CONTEXT cryptCAKey, cryptContext;
1910  time_t writtenValidTo = 0 /* Dummy */, readValidTo;
1911  int dummy, status;
1912 
1913  puts( "Testing renewed certificate write to key file..." );
1914 
1915  /* Get the CA's key and the key to certify */
1916  status = getPrivateKey( &cryptCAKey, CA_PRIVKEY_FILE,
1918  if( cryptStatusError( status ) )
1919  {
1920  printf( "CA private key read failed with error code %d, line %d.\n",
1921  status, __LINE__ );
1922  return( FALSE );
1923  }
1924  if( !loadRSAContexts( CRYPT_UNUSED, NULL, &cryptContext ) )
1925  return( FALSE );
1926 
1927  /* Create the certs containing the keys */
1928  status = cryptCreateCert( &cryptOldCert, CRYPT_UNUSED,
1930  if( cryptStatusOK( status ) )
1931  status = cryptSetAttribute( cryptOldCert,
1932  CRYPT_CERTINFO_SUBJECTPUBLICKEYINFO, cryptContext );
1933  if( cryptStatusOK( status ) && \
1934  !addCertFields( cryptOldCert, certRequestData, __LINE__ ) )
1935  return( FALSE );
1936  if( cryptStatusOK( status ) )
1937  {
1938  time_t validity = time( NULL );
1939 
1940  /* Valid for one month ending tomorrow (we can't make it already-
1941  expired or cryptlib will complain) */
1942  validity += 86400;
1943  cryptSetAttributeString( cryptOldCert,
1944  CRYPT_CERTINFO_VALIDTO, &validity, sizeof( time_t ) );
1945  validity -= ( 86400 * 31 );
1946  status = cryptSetAttributeString( cryptOldCert,
1947  CRYPT_CERTINFO_VALIDFROM, &validity, sizeof( time_t ) );
1948  }
1949  if( cryptStatusOK( status ) )
1950  status = cryptSignCert( cryptOldCert, cryptCAKey );
1951  if( cryptStatusError( status ) )
1952  {
1953  printf( "Signature certificate creation failed with error code %d, "
1954  "line %d.\n", status, __LINE__ );
1955  printErrorAttributeInfo( cryptOldCert );
1956  return( FALSE );
1957  }
1958  status = cryptCreateCert( &cryptNewCert, CRYPT_UNUSED,
1960  if( cryptStatusOK( status ) )
1961  status = cryptSetAttribute( cryptNewCert,
1962  CRYPT_CERTINFO_SUBJECTPUBLICKEYINFO, cryptContext );
1963  if( cryptStatusOK( status ) && \
1964  !addCertFields( cryptNewCert, certRequestData, __LINE__ ) )
1965  return( FALSE );
1966  if( cryptStatusOK( status ) )
1967  {
1968  time_t validity = time( NULL );
1969 
1970  /* Valid for one month starting yesterday (it's actually valid for
1971  one month + one day to sidestep the one-month sanity check in the
1972  private key read code that warns of about-to-expire keys) */
1973  validity -= 86400;
1974  cryptSetAttributeString( cryptNewCert,
1975  CRYPT_CERTINFO_VALIDFROM, &validity, sizeof( time_t ) );
1976  validity += ( 86400 * 32 );
1977  status = cryptSetAttributeString( cryptNewCert,
1978  CRYPT_CERTINFO_VALIDTO, &validity, sizeof( time_t ) );
1979  writtenValidTo = validity;
1980  }
1981  if( cryptStatusOK( status ) )
1982  status = cryptSignCert( cryptNewCert, cryptCAKey );
1983  if( cryptStatusError( status ) )
1984  {
1985  printf( "Encryption certificate creation failed with error code %d, "
1986  "line %d.\n", status, __LINE__ );
1987  printErrorAttributeInfo( cryptNewCert );
1988  return( FALSE );
1989  }
1990  cryptDestroyContext( cryptCAKey );
1991 
1992  /* First, open the keyset, write the key and certificates (using an
1993  in-memory update), and close it. This tests the ability to use
1994  information cached in memory to handle the update */
1995  status = cryptKeysetOpen( &cryptKeyset, CRYPT_UNUSED, CRYPT_KEYSET_FILE,
1997  if( cryptStatusError( status ) )
1998  {
1999  printf( "cryptKeysetOpen() failed with error code %d, line %d.\n",
2000  status, __LINE__ );
2001  return( FALSE );
2002  }
2003  status = cryptAddPrivateKey( cryptKeyset, cryptContext,
2005  if( cryptStatusError( status ) )
2006  {
2007  printExtError( cryptKeyset, "cryptAddPrivateKey()", status,
2008  __LINE__ );
2009  return( FALSE );
2010  }
2011  status = cryptAddPublicKey( cryptKeyset, cryptOldCert );
2012  if( cryptStatusOK( status ) )
2013  status = cryptAddPublicKey( cryptKeyset, cryptNewCert );
2014  if( cryptStatusError( status ) )
2015  {
2016  printExtError( cryptKeyset,
2017  "cryptAddPublicKey() (in-memory update)",
2018  status, __LINE__ );
2019  return( FALSE );
2020  }
2021  status = cryptKeysetClose( cryptKeyset );
2022  if( cryptStatusError( status ) )
2023  {
2024  printf( "cryptKeysetClose() failed with error code %d, line %d.\n",
2025  status, __LINE__ );
2026  return( FALSE );
2027  }
2028 
2029  /* Then try again, but this time perform an on-disk update, closing the
2030  keyset between the first and second update. This tests the ability
2031  to recover the information needed to handle the update from data in
2032  the keyset */
2033  status = cryptKeysetOpen( &cryptKeyset, CRYPT_UNUSED, CRYPT_KEYSET_FILE,
2035  if( cryptStatusOK( status ) )
2036  status = cryptAddPrivateKey( cryptKeyset, cryptContext,
2038  if( cryptStatusOK( status ) )
2039  status = cryptAddPublicKey( cryptKeyset, cryptOldCert );
2040  if( cryptStatusOK( status ) )
2041  status = cryptKeysetClose( cryptKeyset );
2042  if( cryptStatusError( status ) )
2043  {
2044  printf( "Keyset creation in preparation for on-disk update failed "
2045  "with error code %d, line %d.\n", status, __LINE__ );
2046  return( FALSE );
2047  }
2048  status = cryptKeysetOpen( &cryptKeyset, CRYPT_UNUSED, CRYPT_KEYSET_FILE,
2050  if( cryptStatusOK( status ) )
2051  status = cryptAddPublicKey( cryptKeyset, cryptNewCert );
2052  if( cryptStatusError( status ) )
2053  {
2054  printExtError( cryptKeyset, "cryptAddPublicKey() (on-disk update)",
2055  status, __LINE__ );
2056  return( FALSE );
2057  }
2058  status = cryptKeysetClose( cryptKeyset );
2059  if( cryptStatusError( status ) )
2060  {
2061  printf( "cryptKeysetClose() failed with error code %d, line %d.\n",
2062  status, __LINE__ );
2063  return( FALSE );
2064  }
2065 
2066  /* Clean up */
2067  cryptDestroyContext( cryptContext );
2068  cryptDestroyCert( cryptOldCert );
2069  cryptDestroyCert( cryptNewCert );
2070 
2071  /* Try and read the (newest) key+certificate back */
2072  status = getPrivateKey( &cryptContext, RENEW_PRIVKEY_FILE,
2074  if( cryptStatusError( status ) )
2075  {
2076  printf( "Private key read failed with error code %d, line %d.\n",
2077  status, __LINE__ );
2078  return( FALSE );
2079  }
2080  status = cryptGetAttributeString( cryptContext,
2081  CRYPT_CERTINFO_VALIDTO, &readValidTo, &dummy );
2082  if( cryptStatusError( status ) )
2083  return( attrErrorExit( cryptContext, "cryptGetAttributeString",
2084  status, __LINE__ ) );
2085  if( writtenValidTo != readValidTo )
2086  {
2087  const int diff = ( int ) ( readValidTo - writtenValidTo );
2088  const char *units = ( diff % 60 ) ? "seconds" : "minutes";
2089 
2090  printf( "Returned certificate != latest valid certificate, diff.= "
2091  "%d %s, line %d.\n", ( diff % 60 ) ? diff : diff / 60,
2092  units, __LINE__ );
2093  if( diff == 3600 || diff == -3600 )
2094  {
2095  /* See the comment on DST issues in testcert.c */
2096  puts( " (This is probably due to a difference between DST at "
2097  "certificate creation and DST\n now, and isn't a "
2098  "serious problem)." );
2099  }
2100  else
2101  return( FALSE );
2102  }
2103  cryptDestroyContext( cryptContext );
2104 
2105  puts( "Renewed certificate write to key file succeeded.\n" );
2106  return( TRUE );
2107  }
2108 
2109 #else
2110 
2111 int testRenewedCertFile( void )
2112  {
2113  /* Since the renewal is time-based, we can't easily test this under
2114  WinCE */
2115  return( TRUE );
2116  }
2117 #endif /* WinCE */
2118 
2119 /* Test reading various non-cryptlib PKCS #15 files */
2120 
2121 int testReadMiscFile( void )
2122  {
2123  CRYPT_KEYSET cryptKeyset;
2124 /* CRYPT_CONTEXT cryptContext; */
2125  BYTE filenameBuffer[ FILENAME_BUFFER_SIZE ];
2126 #ifdef UNICODE_STRINGS
2127  wchar_t wcBuffer[ FILENAME_BUFFER_SIZE ];
2128 #endif /* UNICODE_STRINGS */
2129  void *fileNamePtr = filenameBuffer;
2130  int status;
2131 
2132  puts( "Testing miscellaneous key file read..." );
2133 
2134  filenameFromTemplate( filenameBuffer, MISC_PRIVKEY_FILE_TEMPLATE, 1 );
2135 #ifdef UNICODE_STRINGS
2136  mbstowcs( wcBuffer, filenameBuffer, strlen( filenameBuffer ) + 1 );
2137  fileNamePtr = wcBuffer;
2138 #endif /* UNICODE_STRINGS */
2139  status = cryptKeysetOpen( &cryptKeyset, CRYPT_UNUSED, CRYPT_KEYSET_FILE,
2140  fileNamePtr, CRYPT_KEYOPT_READONLY );
2141  if( cryptStatusError( status ) )
2142  {
2143  printf( "Couldn't open/scan keyset, status %d, line %d.\n",
2144  status, __LINE__ );
2145  return( FALSE );
2146  }
2147 #if 0
2148  status = cryptGetPrivateKey( cryptKeyset, &cryptContext,
2150  TEXT( "56303156793b318327b25a84808f2cb311c55b0b" ),
2151  TEXT( "PASSWORD" ) );
2152  if( cryptStatusError( status ) )
2153  {
2154  printExtError( cryptKeyset, "cryptGetPrivateKey()", status,
2155  __LINE__ );
2156  return( FALSE );
2157  }
2158 #endif /* 0 */
2159  cryptKeysetClose( cryptKeyset );
2160 
2161  puts( "Miscellaneous key file succeeded.\n" );
2162  return( TRUE );
2163  }
2164 
2165 /* Generic test routines used for debugging */
2166 
2167 void xxxPrivKeyRead( const char *fileName, const char *keyName,
2168  const char *password )
2169  {
2170  CRYPT_KEYSET cryptKeyset;
2172  int status;
2173 
2174  /* Open the file keyset */
2175  status = cryptKeysetOpen( &cryptKeyset, CRYPT_UNUSED, CRYPT_KEYSET_FILE,
2176  fileName, CRYPT_KEYOPT_READONLY );
2177  assert( cryptStatusOK( status ) );
2178 
2179  /* Read the key from the file */
2180  if( password == NULL )
2181  {
2182  status = cryptGetPublicKey( cryptKeyset, &cryptContext,
2183  CRYPT_KEYID_NAME, keyName );
2184  }
2185  else
2186  {
2187  status = cryptGetPrivateKey( cryptKeyset, &cryptContext,
2188  CRYPT_KEYID_NAME, keyName, password );
2189  }
2190  assert( cryptStatusOK( status ) );
2191 
2192  cryptKeysetClose( cryptKeyset );
2193  }
2194 
2195 void xxxPubKeyRead( const char *fileName, const char *keyName )
2196  {
2197  xxxPrivKeyRead( fileName, keyName, NULL );
2198  }
2199 
2200 /****************************************************************************
2201 * *
2202 * Test Key Generation *
2203 * *
2204 ****************************************************************************/
2205 
2206 /* Generate test keys for CA and security protocol use. This enables
2207  various special-case extensions such as extKeyUsages or protocol-specific
2208  AIA entries, as well as using a validity period of 5 years instead of the
2209  usual 1 year to avoid problems when users run the self-test on very old
2210  copies of the code. The keys generated into /test/keys are:
2211 
2212  File define File Description
2213  ----------- ---- -----------
2214  CA_PRIVKEY_FILE ca.p15 Root CA key.
2215  CMP_CA_FILE cmp_ca1.der Written as side-effect of the above.
2216  ICA_PRIVKEY_FILE ca_int.p15 Intermediate CA key + root CA cert.
2217  SCEPCA_PRIVKEY_FILE ca_scep.p15 SCEP CA key + root CA cert, SCEP CA
2218  keyUsage allows encryption + signing.
2219  SCEP_CA_FILE scep_ca1.der Written as side-effect of the above.
2220  SERVER_PRIVKEY_FILE server.p15 SSL server key + root CA cert, server
2221  cert has CN = localhost, OCSP AIA.
2222  SSH_PRIVKEY_FILE ssh1.p15 Raw SSHv1 RSA key.
2223  SSH_PRIVKEY_FILE ssh2.p15 Raw SSHv2 DSA key.
2224  SSH_PRIVKEY_FILE ssh3.p15 Raw SSHv2 ECDSA key.
2225  TSA_PRIVKEY_FILE tsa.p15 TSA server key + root CA cert, TSA
2226  cert has TSP extKeyUsage.
2227  USER_PRIVKEY_FILE user.p15 User key + root CA cert, user cert
2228  has email address.
2229 
2230  (OCSP_CA_FILE is written by the
2231  testCertManagement() code).
2232 
2233  Other keys written by the self-test process are:
2234 
2235  CMP_PRIVKEY_FILE cmp*.p15 Created during the CMP self-test.
2236  DUAL_PRIVKEY_FILE dual.p15 For test of signature + encryption
2237  cert in same file in
2238  testDoubleCertFile().
2239  PNPCA_PRIVKEY_FILE pnp_ca.p15 Created during the PnP PKI self-test,
2240  PNP_PRIVKEY_FILE pnp_user.p15 _ca is for a CA cert request, _user
2241  is for a user cert request.
2242  RENEW_PRIVKEY_FILE renewed.p15 For test of update of older cert with
2243  newer one in testRenewedCertFile().
2244  TEST_PRIVKEY_FILE test.p15 Generic test key file */
2245 
2246 #if 0
2247 
2248 /* Create a standalone private key + certificate */
2249 
2250 static int createCAKeyFile( void )
2251  {
2252  CRYPT_KEYSET cryptKeyset;
2253  CRYPT_CERTIFICATE cryptCert;
2255  FILE *filePtr;
2256  BYTE certBuffer[ BUFFER_SIZE ];
2257  char filenameBuffer[ FILENAME_BUFFER_SIZE ];
2258 #ifndef _WIN32_WCE /* Windows CE doesn't support ANSI C time functions */
2259  const time_t validity = time( NULL ) + ( 86400L * 365 * 3 );
2260 #endif /* _WIN32_WCE */
2261  int length, status;
2262 
2263  /* Create a self-signed CA certificate */
2264  status = cryptCreateContext( &cryptContext, CRYPT_UNUSED, CRYPT_ALGO_RSA );
2265  if( cryptStatusOK( status ) )
2266  status = cryptSetAttributeString( cryptContext, CRYPT_CTXINFO_LABEL,
2269  if( cryptStatusOK( status ) )
2270  status = cryptGenerateKey( cryptContext );
2271  if( cryptStatusError( status ) )
2272  return( status );
2273  status = cryptCreateCert( &cryptCert, CRYPT_UNUSED,
2275  if( cryptStatusOK( status ) )
2276  status = cryptSetAttribute( cryptCert,
2277  CRYPT_CERTINFO_SUBJECTPUBLICKEYINFO, cryptContext );
2278  if( cryptStatusError( status ) )
2279  return( status );
2280  if( !addCertFields( cryptCert, cACertData, __LINE__ ) )
2281  return( CRYPT_ERROR_FAILED );
2282 
2283 #ifndef _WIN32_WCE /* Windows CE doesn't support ANSI C time functions */
2284  /* Make it valid for 5 years instead of 1 to avoid problems when users
2285  run the self-test with very old copies of the code */
2286  cryptSetAttributeString( cryptCert,
2287  CRYPT_CERTINFO_VALIDTO, &validity, sizeof( time_t ) );
2288  if( cryptStatusOK( status ) )
2289  status = cryptSignCert( cryptCert, cryptContext );
2290  if( cryptStatusError( status ) )
2291  return( status );
2292 #endif /* _WIN32_WCE */
2293 
2294  /* Open the keyset, update it with the certificate, and close it */
2295  status = cryptKeysetOpen( &cryptKeyset, CRYPT_UNUSED, CRYPT_KEYSET_FILE,
2297  if( cryptStatusError( status ) )
2298  return( status );
2299  status = cryptAddPrivateKey( cryptKeyset, cryptContext,
2301  if( cryptStatusOK( status ) )
2302  status = cryptAddPublicKey( cryptKeyset, cryptCert );
2303  if( cryptStatusError( status ) )
2304  return( status );
2305 
2306  /* Save the certificate to disk for use in request/response protocols */
2307  status = cryptExportCert( certBuffer, BUFFER_SIZE, &length,
2308  CRYPT_CERTFORMAT_CERTIFICATE, cryptCert );
2309  if( cryptStatusError( status ) )
2310  return( status );
2311  filenameFromTemplate( filenameBuffer, CMP_CA_FILE_TEMPLATE, 1 );
2312  if( ( filePtr = fopen( filenameBuffer, "wb" ) ) != NULL )
2313  {
2314  int count;
2315 
2316  count = fwrite( certBuffer, 1, length, filePtr );
2317  fclose( filePtr );
2318  if( count < length )
2319  {
2320  remove( filenameBuffer );
2321  puts( "Warning: Couldn't save CA certificate to disk, "
2322  "this will cause later\n tests to fail. "
2323  "Press a key to continue." );
2324  getchar();
2325  }
2326  }
2327 
2328  cryptDestroyCert( cryptCert );
2329  cryptDestroyContext( cryptContext );
2330  cryptKeysetClose( cryptKeyset );
2331 
2332  return( CRYPT_OK );
2333  }
2334 
2335 /* Create a raw SSH private key */
2336 
2337 static int createSSHKeyFile( const int keyNo )
2338  {
2339  CRYPT_KEYSET cryptKeyset;
2341  BYTE filenameBuffer[ FILENAME_BUFFER_SIZE ];
2342  int status;
2343 
2344  /* Create a private key */
2345  status = cryptCreateContext( &cryptContext, CRYPT_UNUSED,
2346  ( keyNo == 1 ) ? CRYPT_ALGO_RSA : \
2347  ( keyNo == 2 ) ? CRYPT_ALGO_DSA : \
2348  CRYPT_ALGO_ECDSA );
2349  if( cryptStatusOK( status ) )
2350  status = cryptSetAttributeString( cryptContext, CRYPT_CTXINFO_LABEL,
2353  if( cryptStatusOK( status ) )
2354  status = cryptGenerateKey( cryptContext );
2355  if( cryptStatusError( status ) )
2356  return( status );
2357 
2358  /* Open the keyset, add the key, and close it */
2359  filenameFromTemplate( filenameBuffer, SSH_PRIVKEY_FILE_TEMPLATE, keyNo );
2360  status = cryptKeysetOpen( &cryptKeyset, CRYPT_UNUSED, CRYPT_KEYSET_FILE,
2361  filenameBuffer, CRYPT_KEYOPT_CREATE );
2362  if( cryptStatusError( status ) )
2363  return( status );
2364  status = cryptAddPrivateKey( cryptKeyset, cryptContext,
2366  if( cryptStatusError( status ) )
2367  return( status );
2368  cryptDestroyContext( cryptContext );
2369  cryptKeysetClose( cryptKeyset );
2370 
2371  return( CRYPT_OK );
2372  }
2373 
2374 /* Create a private key + certificate + CA certificate */
2375 
2376 static const CERT_DATA FAR_BSS serverCertRequestData[] = {
2377  /* Identification information */
2378  { CRYPT_CERTINFO_COUNTRYNAME, IS_STRING, 0, TEXT( "NZ" ) },
2379  { CRYPT_CERTINFO_ORGANIZATIONNAME, IS_STRING, 0, TEXT( "Dave's Wetaburgers" ) },
2380  { CRYPT_CERTINFO_ORGANIZATIONALUNITNAME, IS_STRING, 0, TEXT( "Server cert" ) },
2381  { CRYPT_CERTINFO_COMMONNAME, IS_STRING, 0, TEXT( "localhost" ) },
2382 
2383  /* Add an OCSP AIA entry */
2385  { CRYPT_CERTINFO_UNIFORMRESOURCEIDENTIFIER, IS_STRING, 0, TEXT( "http://localhost" ) },
2386  { CRYPT_ATTRIBUTE_NONE, 0, 0, NULL }
2387  };
2388 
2389 static const CERT_DATA FAR_BSS iCACertRequestData[] = {
2390  /* Identification information */
2391  { CRYPT_CERTINFO_COUNTRYNAME, IS_STRING, 0, TEXT( "NZ" ) },
2392  { CRYPT_CERTINFO_ORGANIZATIONNAME, IS_STRING, 0, TEXT( "Dave's Wetaburgers" ) },
2393  { CRYPT_CERTINFO_ORGANIZATIONALUNITNAME, IS_STRING, 0, TEXT( "Intermediate CA cert" ) },
2394  { CRYPT_CERTINFO_COMMONNAME, IS_STRING, 0, TEXT( "Dave's Spare CA" ) },
2395 
2396  /* Set the CA key usage extensions */
2399  { CRYPT_ATTRIBUTE_NONE, 0, 0, NULL }
2400  };
2401 
2402 static const CERT_DATA FAR_BSS scepCACertRequestData[] = {
2403  /* Identification information */
2404  { CRYPT_CERTINFO_COUNTRYNAME, IS_STRING, 0, TEXT( "NZ" ) },
2405  { CRYPT_CERTINFO_ORGANIZATIONNAME, IS_STRING, 0, TEXT( "Dave's Wetaburgers" ) },
2406  { CRYPT_CERTINFO_ORGANIZATIONALUNITNAME, IS_STRING, 0, TEXT( "SCEP CA cert" ) },
2407  { CRYPT_CERTINFO_COMMONNAME, IS_STRING, 0, TEXT( "Dave's SCEP CA" ) },
2408 
2409  /* Set the CA as well as generic sign+encrypt key usage extensions */
2412  CRYPT_KEYUSAGE_DIGITALSIGNATURE | \
2413  CRYPT_KEYUSAGE_KEYENCIPHERMENT },
2414  { CRYPT_ATTRIBUTE_NONE, 0, 0, NULL }
2415  };
2416 
2417 static const CERT_DATA FAR_BSS tsaCertRequestData[] = {
2418  /* Identification information */
2419  { CRYPT_CERTINFO_COUNTRYNAME, IS_STRING, 0, TEXT( "NZ" ) },
2420  { CRYPT_CERTINFO_ORGANIZATIONNAME, IS_STRING, 0, TEXT( "Dave's Wetaburgers" ) },
2421  { CRYPT_CERTINFO_ORGANIZATIONALUNITNAME, IS_STRING, 0, TEXT( "TSA Cert" ) },
2422  { CRYPT_CERTINFO_COMMONNAME, IS_STRING, 0, TEXT( "Dave's TSA" ) },
2423 
2424  /* Set the TSP extended key usage */
2427  { CRYPT_ATTRIBUTE_NONE, 0, 0, NULL }
2428  };
2429 
2430 static const CERT_DATA FAR_BSS userCertRequestData[] = {
2431  /* Identification information */
2432  { CRYPT_CERTINFO_COUNTRYNAME, IS_STRING, 0, TEXT( "NZ" ) },
2433  { CRYPT_CERTINFO_ORGANIZATIONNAME, IS_STRING, 0, TEXT( "Dave's Wetaburgers" ) },
2434  { CRYPT_CERTINFO_ORGANIZATIONALUNITNAME, IS_STRING, 0, TEXT( "Procurement" ) },
2435  { CRYPT_CERTINFO_COMMONNAME, IS_STRING, 0, TEXT( "Dave Smith" ) },
2437  { CRYPT_ATTRIBUTE_CURRENT, IS_NUMERIC, CRYPT_CERTINFO_SUBJECTNAME }, /* Re-select subject DN */
2438 
2439  { CRYPT_ATTRIBUTE_NONE, 0, 0, NULL }
2440  };
2441 
2442 int createTestKeys( void )
2443  {
2444  char filenameBuffer[ FILENAME_BUFFER_SIZE ];
2445 #ifdef UNICODE_STRINGS
2446  wchar_t wcBuffer[ FILENAME_BUFFER_SIZE ];
2447 #endif /* UNICODE_STRINGS */
2448  void *fileNamePtr = filenameBuffer;
2449  int status;
2450 
2451  puts( "Creating custom key files and associated certificate files..." );
2452 
2454  NULL ) == CRYPT_ERROR_NOTAVAIL )
2455  {
2456  puts( "Error: ECDSA must be enabled to create the custom key "
2457  "files." );
2458  return( FALSE );
2459  }
2460 
2461  printf( "CA root key + CMP request certificate... " );
2462  status = createCAKeyFile();
2463  if( cryptStatusOK( status ) )
2464  {
2465  printf( "done.\nSSH RSA server key..." );
2466  status = createSSHKeyFile( 1 );
2467  }
2468  if( cryptStatusOK( status ) )
2469  {
2470  printf( "done.\nSSH DSA server key..." );
2471  status = createSSHKeyFile( 2 );
2472  }
2473  if( cryptStatusOK( status ) )
2474  {
2475  printf( "done.\nSSH ECC server key..." );
2476  status = createSSHKeyFile( 3 );
2477  }
2478  if( cryptStatusOK( status ) )
2479  {
2480  printf( "done.\nSSL/TLS RSA server key..." );
2481 
2482  filenameFromTemplate( filenameBuffer, SERVER_PRIVKEY_FILE_TEMPLATE, 1 );
2483 #ifdef UNICODE_STRINGS
2484  mbstowcs( wcBuffer, filenameBuffer, strlen( filenameBuffer ) + 1 );
2485  fileNamePtr = wcBuffer;
2486 #endif /* UNICODE_STRINGS */
2487  if( !writeFileCertChain( serverCertRequestData, fileNamePtr,
2488  NULL, FALSE, FALSE, CRYPT_ALGO_RSA,
2489  CRYPT_USE_DEFAULT ) )
2490  status = CRYPT_ERROR_FAILED;
2491  }
2492  if( cryptStatusOK( status ) )
2493  {
2494  printf( "done.\nSSL/TLS ECC P256 server key..." );
2495 
2496  filenameFromTemplate( filenameBuffer, SERVER_ECPRIVKEY_FILE_TEMPLATE, 256 );
2497 #ifdef UNICODE_STRINGS
2498  mbstowcs( wcBuffer, filenameBuffer, strlen( filenameBuffer ) + 1 );
2499  fileNamePtr = wcBuffer;
2500 #endif /* UNICODE_STRINGS */
2501  if( !writeFileCertChain( serverCertRequestData, fileNamePtr,
2502  NULL, FALSE, FALSE, CRYPT_ALGO_ECDSA,
2503  CRYPT_USE_DEFAULT ) )
2504  status = CRYPT_ERROR_FAILED;
2505  }
2506  if( cryptStatusOK( status ) )
2507  {
2508  printf( "done.\nSSL/TLS ECC P384 server key..." );
2509 
2510  filenameFromTemplate( filenameBuffer, SERVER_ECPRIVKEY_FILE_TEMPLATE, 384 );
2511 #ifdef UNICODE_STRINGS
2512  mbstowcs( wcBuffer, filenameBuffer, strlen( filenameBuffer ) + 1 );
2513  fileNamePtr = wcBuffer;
2514 #endif /* UNICODE_STRINGS */
2515  if( !writeFileCertChain( serverCertRequestData, fileNamePtr,
2516  NULL, FALSE, FALSE, CRYPT_ALGO_ECDSA,
2517  48 /* P384 */ ) )
2518  status = CRYPT_ERROR_FAILED;
2519  }
2520  if( cryptStatusOK( status ) )
2521  {
2522  printf( "done.\nSSL/TLS ECC P521 server key..." );
2523 
2524  filenameFromTemplate( filenameBuffer, SERVER_ECPRIVKEY_FILE_TEMPLATE, 521 );
2525 #ifdef UNICODE_STRINGS
2526  mbstowcs( wcBuffer, filenameBuffer, strlen( filenameBuffer ) + 1 );
2527  fileNamePtr = wcBuffer;
2528 #endif /* UNICODE_STRINGS */
2529  if( !writeFileCertChain( serverCertRequestData, fileNamePtr,
2530  NULL, FALSE, FALSE, CRYPT_ALGO_ECDSA,
2531  66 /* P521 */ ) )
2532  status = CRYPT_ERROR_FAILED;
2533  }
2534  if( cryptStatusOK( status ) )
2535  {
2536  printf( "done.\nIntermediate CA key..." );
2537  if( !writeFileCertChain( iCACertRequestData, ICA_PRIVKEY_FILE,
2538  NULL, FALSE, FALSE, CRYPT_ALGO_RSA,
2539  CRYPT_USE_DEFAULT ) )
2540  status = CRYPT_ERROR_FAILED;
2541  }
2542  if( cryptStatusOK( status ) )
2543  {
2544  printf( "done.\nSCEP CA key + SCEP request certificate..." );
2545  filenameFromTemplate( filenameBuffer, SCEP_CA_FILE_TEMPLATE, 1 );
2546 #ifdef UNICODE_STRINGS
2547  mbstowcs( wcBuffer, filenameBuffer, strlen( filenameBuffer ) + 1 );
2548  fileNamePtr = wcBuffer;
2549 #endif /* UNICODE_STRINGS */
2550  if( !writeFileCertChain( scepCACertRequestData, SCEPCA_PRIVKEY_FILE,
2551  fileNamePtr, FALSE, FALSE, CRYPT_ALGO_RSA,
2552  CRYPT_USE_DEFAULT ) )
2553  status = CRYPT_ERROR_FAILED;
2554  }
2555  if( cryptStatusOK( status ) )
2556  {
2557  printf( "done.\nTSA key..." );
2558  if( !writeFileCertChain( tsaCertRequestData, TSA_PRIVKEY_FILE,
2559  NULL, FALSE, FALSE, CRYPT_ALGO_RSA,
2560  CRYPT_USE_DEFAULT ) )
2561  status = CRYPT_ERROR_FAILED;
2562  }
2563  if( cryptStatusOK( status ) )
2564  {
2565  printf( "done.\nUser key..." );
2566  if( !writeFileCertChain( userCertRequestData, USER_PRIVKEY_FILE,
2567  NULL, FALSE, FALSE, CRYPT_ALGO_RSA,
2568  CRYPT_USE_DEFAULT ) )
2569  status = CRYPT_ERROR_FAILED;
2570  }
2571  if( cryptStatusError( status ) )
2572  {
2573  puts( "\nCustom key file create failed.\n" );
2574  return( FALSE );
2575  }
2576  puts( "done." );
2577 
2578  puts( "Custom key file creation succeeded.\n" );
2579  return( TRUE );
2580  }
2581 #endif /* 0 */
2582 
2583 #endif /* TEST_KEYSET */