cryptlib  3.4.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Macros
certimp.c
Go to the documentation of this file.
1 /****************************************************************************
2 * *
3 * cryptlib Certificate Handling Test Routines *
4 * Copyright Peter Gutmann 1997-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 /****************************************************************************
20 * *
21 * Utility Routines *
22 * *
23 ****************************************************************************/
24 
25 /* Handle various types of certificate-processing errors */
26 
27 static BOOLEAN handleCertImportError( const int errorCode, const int lineNo )
28  {
29  printf( "cryptImportCert() failed with error code %d, line %d.\n",
30  errorCode, lineNo );
31  return( FALSE );
32  }
33 
34 /****************************************************************************
35 * *
36 * Certificate Import Routines Test *
37 * *
38 ****************************************************************************/
39 
40 /* Test certificate import code */
41 
42 static BOOLEAN handleCertError( const CRYPT_CERTIFICATE cryptCert,
43  const int certNo, const int errorCode )
44  {
45  int errorLocus, status;
46 
47  printf( "\n" );
48  status = cryptGetAttribute( cryptCert, CRYPT_ATTRIBUTE_ERRORLOCUS,
49  &errorLocus );
50  if( cryptStatusError( status ) )
51  {
52  puts( "Couldn't get error locus for certificate check failure." );
53  return( FALSE );
54  }
55 
56  /* Make sure that we don't fail just because the certificate that we're
57  using as a test has expired */
58  if( errorLocus == CRYPT_CERTINFO_VALIDTO )
59  {
60  puts( "Warning: Validity check failed because the certificate has "
61  "expired." );
62  return( TRUE );
63  }
64 
65  /* RegTP CA certs are marked as non-CA certs, report the problem and
66  continue */
67  if( certNo == 3 && errorLocus == CRYPT_CERTINFO_CA )
68  {
69  puts( "Warning: Validity check failed due to RegTP CA certificate "
70  "incorrectly\n marked as non-CA certificate." );
71  return( TRUE );
72  }
73 
74  /* Certificate #26 has an invalid keyUsage for the key it contains, it's
75  used in order to check for the ability to handle a non-hole BIT
76  STRING in a location where a hole encoding is normally used so we
77  don't care about this particular problem */
78  if( certNo == 26 && errorLocus == CRYPT_CERTINFO_KEYUSAGE )
79  {
80  puts( "Warning: Validity check failed due to CA certificate with "
81  "incorrect\n key usage field (this will be ignored "
82  "since the certificate\n is used to test for other "
83  "error handling conditions)." );
84  return( TRUE );
85  }
86 
87  return( FALSE );
88  }
89 
90 static int certImport( const int certNo, const BOOLEAN isECC,
91  const BOOLEAN isBase64 )
92  {
93  CRYPT_CERTIFICATE cryptCert;
94  FILE *filePtr;
96  int count, value, status;
97 
98  printf( "Testing %scertificate #%d import...\n",
99  isECC ? "ECC " : isBase64 ? "base64 " : "", certNo );
100  filenameFromTemplate( buffer, isECC ? ECC_CERT_FILE_TEMPLATE : \
101  isBase64 ? BASE64CERT_FILE_TEMPLATE : \
102  CERT_FILE_TEMPLATE, certNo );
103  if( ( filePtr = fopen( buffer, "rb" ) ) == NULL )
104  {
105  puts( "Couldn't find certificate file for import test." );
106  return( FALSE );
107  }
108  count = fread( buffer, 1, BUFFER_SIZE, filePtr );
109  fclose( filePtr );
110 
111  /* Import the certificate */
112  status = cryptImportCert( buffer, count, CRYPT_UNUSED,
113  &cryptCert );
114  if( status == CRYPT_ERROR_NOSECURE && !( isECC || isBase64 ) && \
115  ( certNo == 9 || certNo == 10 ) ) /* 9 = 512-bit, 10 = P12 512-bit */
116  {
117  /* Some older certs use totally insecure 512-bit keys and can't be
118  processed unless we deliberately allow insecure keys.
119  Unfortunately this also blocks out the certificate that's used to
120  check the ability to handle invalid PKCS #1 padding, since this
121  only uses a 512-bit key, but if necessary it can be tested by
122  lowering MIN_PKCSIZE when building cryptlib */
123  puts( "Warning: Certificate import failed because the certificate "
124  "uses a very short\n (insecure) key.\n" );
125  return( TRUE );
126  }
127  if( status == CRYPT_ERROR_BADDATA && !( isECC || isBase64 ) \
128  && certNo == 3 )
129  {
130  puts( "Warning: Certificate import failed for RegTP/Deutsche "
131  "Telekom CA\n certificate with negative public-key "
132  "values.\n" );
133  return( TRUE );
134  }
135  if( status == CRYPT_ERROR_NOTAVAIL && !( isECC || isBase64 ) && \
136  certNo == 21 )
137  {
138  /* This is an ECDSA certificate, the algorithm isn't enabled by
139  default */
140  puts( "Warning: Certificate import failed because the certificate "
141  "uses an\n algorithm that isn't enabled in this build "
142  "of cryptlib.\n" );
143  return( TRUE );
144  }
145  if( cryptStatusError( status ) )
146  {
147  printf( "cryptImportCert() for certificate #%d failed with error "
148  "code %d, line %d.\n", certNo, status, __LINE__ );
149  return( FALSE );
150  }
151  status = cryptGetAttribute( cryptCert, CRYPT_CERTINFO_SELFSIGNED,
152  &value );
153  if( cryptStatusError( status ) )
154  {
155  /* Sanity check to make sure that the certificate internal state is
156  consistent - this should never happen */
157  printf( "Couldn't get certificate self-signed status, status %d, "
158  "line %d.\n", status, __LINE__ );
159  return( FALSE );
160  }
161  if( value )
162  {
163  printf( "Certificate is self-signed, checking signature... " );
164  status = cryptCheckCert( cryptCert, CRYPT_UNUSED );
165  if( cryptStatusError( status ) )
166  {
167  if( !handleCertError( cryptCert, certNo, status ) )
168  {
169  return( attrErrorExit( cryptCert, "cryptCheckCert()",
170  status, __LINE__ ) );
171  }
172  }
173  else
174  puts( "signature verified." );
175  }
176  else
177  puts( "Certificate is signed, signature key unknown." );
178 
179  /* Print information on what we've got */
180  if( !printCertInfo( cryptCert ) )
181  return( FALSE );
182 
183  /* Clean up */
184  cryptDestroyCert( cryptCert );
185  puts( "Certificate import succeeded.\n" );
186  return( TRUE );
187  }
188 
189 #if 0 /* Test rig for NISCC certificate data */
190 
191 static void importTestData( void )
192  {
193  int i;
194 
195  for( i = 1; i <= 110000; i++ )
196  {
197  CRYPT_CERTIFICATE cryptCert;
198  FILE *filePtr;
199  BYTE buffer[ BUFFER_SIZE ];
200  int count, status;
201 
202  if( !( i % 100 ) )
203  printf( "%06d\r", i );
204 /* filenameFromTemplate( buffer, "/tmp/simple_client/%08d", i ); */
205 /* filenameFromTemplate( buffer, "/tmp/simple_server/%08d", i ); */
206  filenameFromTemplate( buffer, "/tmp/simple_rootca/%08d", i );
207  if( ( filePtr = fopen( buffer, "rb" ) ) == NULL )
208  break;
209  count = fread( buffer, 1, BUFFER_SIZE, filePtr );
210  fclose( filePtr );
211  status = cryptImportCert( buffer, count, CRYPT_UNUSED,
212  &cryptCert );
213  if( cryptStatusOK( status ) )
214  cryptDestroyCert( cryptCert );
215  }
216  }
217 #endif /* 0 */
218 
219 int testCertImport( void )
220  {
221  int i;
222 
223  for( i = 1; i <= 30; i++ )
224  {
225  if( !certImport( i, FALSE, FALSE ) )
226  return( FALSE );
227  }
228  return( TRUE );
229  }
230 
231 int testCertImportECC( void )
232  {
233  int i;
234 
236  {
237  puts( "ECC algorithm support appears to be disabled, skipping "
238  "processing of ECDSA\ncertificates.\n" );
239  return( TRUE );
240  }
241 
242  for( i = 1; i <= 10; i++ )
243  {
244  if( !certImport( i, TRUE, FALSE ) )
245  return( FALSE );
246  }
247  return( TRUE );
248  }
249 
250 static int certReqImport( const int certNo )
251  {
252  CRYPT_CERTIFICATE cryptCert;
253  FILE *filePtr;
254  BYTE buffer[ BUFFER_SIZE ];
255  int count, complianceValue, status;
256 
257  printf( "Testing certificate request #%d import...\n", certNo );
258  filenameFromTemplate( buffer, CERTREQ_FILE_TEMPLATE, certNo );
259  if( ( filePtr = fopen( buffer, "rb" ) ) == NULL )
260  {
261  puts( "Couldn't find certificate file for import test." );
262  return( FALSE );
263  }
264  count = fread( buffer, 1, BUFFER_SIZE, filePtr );
265  fclose( filePtr );
266 
267  /* Import the certificate request and check that the signature is valid */
268  if( certNo == 3 )
269  {
270  /* Some of the requests are broken and we have to set the compliance
271  level to oblivious to handle them */
273  &complianceValue );
276  }
277  status = cryptImportCert( buffer, count, CRYPT_UNUSED,
278  &cryptCert );
279  if( certNo == 3 )
280  {
282  complianceValue );
283  }
284 #ifdef __UNIX__
285  if( status == CRYPT_ERROR_NOTAVAIL || status == CRYPT_ERROR_BADDATA )
286  {
287  puts( "The certificate request import failed, probably because "
288  "you're using an\nolder version of unzip that corrupts "
289  "certain types of files when it\nextracts them. To fix this, "
290  "you need to re-extract test/*.der without\nusing the -a "
291  "option to convert text files.\n" );
292  return( TRUE ); /* Skip this test and continue */
293  }
294 #endif /* __UNIX__ */
295  if( status == CRYPT_ERROR_NOSECURE && certNo == 1 )
296  {
297  puts( "Warning: Certificate request import failed because the "
298  "request uses a very short\n (insecure) key." );
299  return( TRUE );
300  }
301  if( cryptStatusError( status ) )
302  return( handleCertImportError( status, __LINE__ ) );
303  if( certNo == 5 )
304  puts( " (Skipping signature check because CRMF data is unsigned)." );
305  else
306  {
307  printf( "Checking signature... " );
308  status = cryptCheckCert( cryptCert, CRYPT_UNUSED );
309  if( cryptStatusError( status ) )
310  return( attrErrorExit( cryptCert, "cryptCheckCert()", status,
311  __LINE__ ) );
312  puts( "signature verified." );
313  }
314 
315  /* Print information on what we've got */
316  if( !printCertInfo( cryptCert ) )
317  return( FALSE );
318 
319  /* Clean up */
320  cryptDestroyCert( cryptCert );
321  puts( "Certificate request import succeeded.\n" );
322  return( TRUE );
323  }
324 
325 int testCertReqImport( void )
326  {
327  int i;
328 
329  for( i = 1; i <= 5; i++ )
330  {
331  if( !certReqImport( i ) )
332  return( FALSE );
333  }
334  return( TRUE );
335  }
336 
337 #define LARGE_CRL_SIZE 32767 /* Large CRL is too big for std.buffer */
338 
339 static int crlImport( const int crlNo, BYTE *buffer )
340  {
341  CRYPT_CERTIFICATE cryptCert;
342  FILE *filePtr;
343  int count, status;
344 
345  filenameFromTemplate( buffer, CRL_FILE_TEMPLATE, crlNo );
346  if( ( filePtr = fopen( buffer, "rb" ) ) == NULL )
347  {
348  printf( "Couldn't find CRL file for CRL #%d import test.\n", crlNo );
349  return( FALSE );
350  }
351  count = fread( buffer, 1, LARGE_CRL_SIZE, filePtr );
352  fclose( filePtr );
353  printf( "CRL #%d has size %d bytes.\n", crlNo, count );
354 
355  /* Import the CRL. Since CRL's don't include the signing certificate,
356  we can't (easily) check the signature on it */
357  status = cryptImportCert( buffer, count, CRYPT_UNUSED,
358  &cryptCert );
359  if( cryptStatusError( status ) )
360  return( handleCertImportError( status, __LINE__ ) );
361 
362  /* Print information on what we've got and clean up */
363  if( !printCertInfo( cryptCert ) )
364  return( FALSE );
365  cryptDestroyCert( cryptCert );
366 
367  return( TRUE );
368  }
369 
370 int testCRLImport( void )
371  {
372  BYTE *bufPtr;
373  int i;
374 
375  puts( "Testing CRL import..." );
376 
377  /* Since we're working with an unusually large certificate object we
378  have to dynamically allocate the buffer for it */
379  if( ( bufPtr = malloc( LARGE_CRL_SIZE ) ) == NULL )
380  {
381  puts( "Out of memory." );
382  return( FALSE );
383  }
384  for( i = 1; i <= 3; i++ )
385  {
386  if( !crlImport( i, bufPtr ) )
387  return( FALSE );
388  }
389 
390  /* Clean up */
391  free( bufPtr );
392  puts( "CRL import succeeded.\n" );
393  return( TRUE );
394  }
395 
396 static BOOLEAN isSingleCert( const CRYPT_CERTIFICATE cryptCertChain )
397  {
398  int value, status;
399 
400  /* Check whether a certificate chain contains a single non-self-signed
401  certificate, which means that we can't perform a signature check on
402  it */
403  status = cryptGetAttribute( cryptCertChain, CRYPT_CERTINFO_SELFSIGNED,
404  &value );
405  if( cryptStatusOK( status ) && value )
406  {
407  /* It's a self-signed certificate, we should be able to check this
408  chain */
409  return( FALSE );
410  }
413  if( cryptSetAttribute( cryptCertChain,
416  {
417  /* There's only a single certificate in the chain and it's not self-
418  signed, we can't check it */
419  return( TRUE );
420  }
421 
422  return( FALSE );
423  }
424 
425 static int checkExpiredCertChain( const CRYPT_CERTIFICATE cryptCertChain )
426  {
427  int complianceValue, status;
428 
429  printf( "Warning: The certificate chain didn't verify because one or "
430  "more\n certificates in it have expired. Trying again "
431  "in oblivious\n mode... " );
433  &complianceValue );
436  status = cryptCheckCert( cryptCertChain, CRYPT_UNUSED );
438  complianceValue );
439 
440  return( status );
441  }
442 
443 static BOOLEAN handleCertChainError( const CRYPT_CERTIFICATE cryptCertChain,
444  const int certNo, const int errorCode )
445  {
446  int trustValue = CRYPT_UNUSED, errorLocus, status;
447 
448  /* If the chain contains a single non-CA certificate, we'll get a
449  parameter error since we haven't supplied a signing certificate */
450  if( errorCode == CRYPT_ERROR_PARAM2 && isSingleCert( cryptCertChain ) )
451  {
452  /* There's only a single certificate present, we can't do much with
453  it */
454  puts( "\nCertificate chain contains only a single standalone "
455  "certificate, skipping\nsignature check..." );
456  return( TRUE );
457  }
458 
459  /* If it's not a problem with validity, we can't go any further */
460  if( errorCode != CRYPT_ERROR_INVALID )
461  {
462  return( attrErrorExit( cryptCertChain, "cryptCheckCert()",
463  errorCode, __LINE__ ) );
464  }
465 
466  /* Check the nature of the problem */
467  status = cryptGetAttribute( cryptCertChain, CRYPT_ATTRIBUTE_ERRORLOCUS,
468  &errorLocus );
469  if( cryptStatusError( status ) )
470  {
471  puts( "Couldn't get error locus for certificate check failure." );
472  return( FALSE );
473  }
474 
475  /* Try to work around the error */
476  status = errorCode;
477  if( errorLocus == CRYPT_CERTINFO_TRUSTED_IMPLICIT || \
478  errorLocus == CRYPT_CERTINFO_TRUSTED_USAGE )
479  {
480  /* The error occured because of a problem with the root certificate,
481  try again with an implicitly-trusted root */
482  if( errorLocus == CRYPT_CERTINFO_TRUSTED_IMPLICIT )
483  {
484  printf( "\nWarning: The certificate chain didn't verify "
485  "because it didn't end in a\n trusted root "
486  "certificate. Checking again using an "
487  "implicitly\n trusted root... " );
488  }
489  else
490  {
491  printf( "\nWarning: The certificate chain didn't verify "
492  "because the root certificate's\n key isn't "
493  "enabled for this usage. Checking again using "
494  "an\n implicitly trusted root... " );
495  }
496  if( cryptStatusError( \
497  setRootTrust( cryptCertChain, &trustValue, 1 ) ) )
498  {
499  printf( "\nAttempt to make chain root implicitly trusted "
500  "failed, status = %d, line %d.\n", status, __LINE__ );
501  return( FALSE );
502  }
503  status = cryptCheckCert( cryptCertChain, CRYPT_UNUSED );
504  if( status == CRYPT_ERROR_INVALID )
506  &errorLocus );
507  }
508  if( errorLocus == CRYPT_CERTINFO_VALIDTO )
509  {
510  /* One (or more) certs in the chain have expired, try again with the
511  compliance level wound down to nothing */
512  putchar( '\n' );
513  status = checkExpiredCertChain( cryptCertChain );
514  if( status == CRYPT_ERROR_PARAM2 && isSingleCert( cryptCertChain ) )
515  {
516  /* There's only a single certificate present, we can't do much
517  with it */
518  puts( "\nCertificate chain contains only a single standalone "
519  "certificate, skipping\nsignature check..." );
520  return( TRUE );
521  }
522  }
523  if( errorLocus == CRYPT_CERTINFO_CERTIFICATE )
524  {
525  puts( "\nCertificate chain is incomplete (one or more certificates "
526  "needed to\ncomplete the chain are missing), skipping "
527  "signature check..." );
528  return( TRUE );
529  }
530 
531  /* If we changed settings, restore their original values */
532  if( trustValue != CRYPT_UNUSED )
533  setRootTrust( cryptCertChain, NULL, trustValue );
534 
535  /* If we've got a long-enough chain, try again with the next-to-last
536  certificate marked as trusted */
537  if( cryptStatusOK( status ) && certNo == 4 )
538  {
539  puts( "signatures verified." );
540  puts( "Checking again with an intermediate certificate marked as "
541  "trusted... " );
542  status = cryptSetAttribute( cryptCertChain,
545  if( cryptStatusOK( status ) )
546  status = cryptSetAttribute( cryptCertChain,
549  if( cryptStatusOK( status ) )
550  status = cryptSetAttribute( cryptCertChain,
552  if( cryptStatusError( status ) )
553  return( status );
554  status = cryptCheckCert( cryptCertChain, CRYPT_UNUSED );
555  if( status == CRYPT_ERROR_INVALID )
556  {
558  &errorLocus );
559  if( errorLocus == CRYPT_CERTINFO_VALIDTO )
560  {
561  /* One (or more) certs in the chain have expired, try again
562  with the compliance level wound down to nothing */
563  status = checkExpiredCertChain( cryptCertChain );
564  }
565  }
566  if( trustValue != CRYPT_UNUSED )
567  {
568  cryptSetAttribute( cryptCertChain,
570  trustValue );
571  }
572  }
573 
574  /* If the lowered-limits check still didn't work, it's an error */
575  if( cryptStatusError( status ) )
576  {
577  putchar( '\n' );
578  return( attrErrorExit( cryptCertChain, "cryptCheckCert()", status,
579  __LINE__ ) );
580  }
581 
582  puts( "signatures verified." );
583  return( TRUE );
584  }
585 
586 static int certChainImport( const int certNo, const BOOLEAN isBase64 )
587  {
588  CRYPT_CERTIFICATE cryptCertChain;
589  FILE *filePtr;
590  BYTE buffer[ BUFFER_SIZE ];
591  int count, value, status;
592 
593  printf( "Testing %scert chain #%d import...\n",
594  isBase64 ? "base64 " : "", certNo );
596  CERTCHAIN_FILE_TEMPLATE, certNo );
597  if( ( filePtr = fopen( buffer, "rb" ) ) == NULL )
598  {
599  puts( "Couldn't find certificate chain file for import test." );
600  return( FALSE );
601  }
602  count = fread( buffer, 1, BUFFER_SIZE, filePtr );
603  fclose( filePtr );
604  if( count == BUFFER_SIZE )
605  {
606  puts( "The certificate buffer size is too small for the certificate "
607  "chain. To fix\nthis, increase the BUFFER_SIZE value in "
608  "test/testcert.c and recompile the code." );
609  return( TRUE ); /* Skip this test and continue */
610  }
611  printf( "Certificate chain has size %d bytes.\n", count );
612 
613  /* Import the certificate chain. This assumes that the default certs are
614  installed as trusted certs, which is required for cryptCheckCert() */
615  status = cryptImportCert( buffer, count, CRYPT_UNUSED,
616  &cryptCertChain );
617  if( cryptStatusError( status ) )
618  {
619  /* If we failed on the RSA e=3 certificate, this is a valid result */
620  if( certNo == 2 && status == CRYPT_ERROR_BADDATA )
621  {
622  printf( "Import of certificate with invalid e=3 key failed, "
623  "line %d.\n", __LINE__ );
624  puts( " (This is the correct result for this test).\n" );
625  return( TRUE );
626  }
627  return( handleCertImportError( status, __LINE__ ) );
628  }
629  if( certNo == 2 )
630  {
631  printf( "Import of certificate with invalid e=3 key succeeded when "
632  "it should have\n failed, line %d.\n", __LINE__ );
633  return( FALSE );
634  }
635  status = cryptGetAttribute( cryptCertChain, CRYPT_CERTINFO_CERTTYPE,
636  &value );
637  if( cryptStatusError( status ) )
638  return( attrErrorExit( cryptCertChain, "cryptGetAttribute()",
639  status, __LINE__ ) );
640  if( certNo == 1 )
641  {
642  /* The first chain has length 1 so it should be imported as a
643  standard certificate */
644  if( value != CRYPT_CERTTYPE_CERTIFICATE )
645  {
646  printf( "Imported object isn't a certificate, line %d.\n",
647  __LINE__ );
648  return( FALSE );
649  }
650  }
651  else
652  {
653  if( value != CRYPT_CERTTYPE_CERTCHAIN )
654  {
655  printf( "Imported object isn't a certificate chain, line %d.\n",
656  __LINE__ );
657  return( FALSE );
658  }
659  }
660  printf( "Checking signatures... " );
661  status = cryptCheckCert( cryptCertChain, CRYPT_UNUSED );
662  if( cryptStatusError( status ) )
663  {
664  if( !handleCertChainError( cryptCertChain, certNo, status ) )
665  return( FALSE );
666  }
667  else
668  puts( "signatures verified." );
669 
670  /* Display info on each certificate in the chain */
671  if( !printCertChainInfo( cryptCertChain ) )
672  return( FALSE );
673 
674  /* Clean up */
675  cryptDestroyCert( cryptCertChain );
676  puts( "Certificate chain import succeeded.\n" );
677  return( TRUE );
678  }
679 
681  {
682  int i;
683 
684  for( i = 1; i <= 5; i++ )
685  {
686  if( !certChainImport( i, FALSE ) )
687  return( FALSE );
688  }
689  return( TRUE );
690  }
691 
692 int testOCSPImport( void )
693  {
694  CRYPT_CERTIFICATE cryptCert, cryptResponderCert;
695  FILE *filePtr;
696  BYTE buffer[ BUFFER_SIZE ];
697  int count, status;
698 
699  if( ( filePtr = fopen( convertFileName( OCSP_OK_FILE ), "rb" ) ) == NULL )
700  {
701  puts( "Couldn't find OCSP OK response file for import test." );
702  return( FALSE );
703  }
704  puts( "Testing OCSP OK response import..." );
705  count = fread( buffer, 1, BUFFER_SIZE, filePtr );
706  fclose( filePtr );
707  printf( "OCSP OK response has size %d bytes.\n", count );
708 
709  /* Import the OCSP OK response. Because of the choose-your-own-trust-
710  model status of the OCSP RFC we have to supply our own signature
711  check certificate to verify the response */
712  status = cryptImportCert( buffer, count, CRYPT_UNUSED,
713  &cryptCert );
714  if( cryptStatusError( status ) )
715  return( handleCertImportError( status, __LINE__ ) );
716  printf( "Checking signature... " );
717  status = importCertFile( &cryptResponderCert, OCSP_CA_FILE );
718  if( cryptStatusOK( status ) )
719  {
720  status = cryptCheckCert( cryptCert, cryptResponderCert );
721  cryptDestroyCert( cryptResponderCert );
722  }
723  if( cryptStatusError( status ) )
724  return( attrErrorExit( cryptCert, "cryptCheckCert()", status,
725  __LINE__ ) );
726  puts( "signatures verified." );
727 
728  /* Print information on what we've got */
729  if( !printCertInfo( cryptCert ) )
730  return( FALSE );
731  cryptDestroyCert( cryptCert );
732 
733  /* Now import the OCSP revoked response. This has a different CA
734  certificate than the OK response, to keep things simple we don't
735  bother with a sig check for this one */
736  puts( "Testing OCSP revoked response import..." );
737  if( ( filePtr = fopen( convertFileName( OCSP_REV_FILE ), "rb" ) ) == NULL )
738  {
739  puts( "Couldn't find OCSP revoked response file for import test." );
740  return( FALSE );
741  }
742  count = fread( buffer, 1, BUFFER_SIZE, filePtr );
743  fclose( filePtr );
744  printf( "OCSP revoked response has size %d bytes.\n", count );
745  status = cryptImportCert( buffer, count, CRYPT_UNUSED,
746  &cryptCert );
747  if( cryptStatusError( status ) )
748  return( handleCertImportError( status, __LINE__ ) );
749 
750  /* Print information on what we've got */
751  if( !printCertInfo( cryptCert ) )
752  return( FALSE );
753 
754  /* Clean up */
755  cryptDestroyCert( cryptCert );
756  puts( "OCSP import succeeded.\n" );
757  return( TRUE );
758  }
759 
761  {
762  int i;
763 
764  /* If this is an EBCDIC system, we can't (easily) import the base64-
765  encoded certificate without complex calisthenics to handle the
766  different character sets */
767 #if 'A' == 0xC1
768  puts( "Skipping import of base64-encoded data on EBCDIC system.\n" );
769  return( TRUE );
770 #endif /* EBCDIC system */
771 
772  for( i = 1; i <= 2; i++ )
773  {
774  if( !certImport( i, FALSE, TRUE ) )
775  return( FALSE );
776  }
777  return( TRUE );
778  }
779 
781  {
782  int i;
783 
784  /* If this is an EBCDIC system, we can't (easily) import the base64-
785  encoded certificate without complex calisthenics to handle the
786  different character sets */
787 #if 'A' == 0xC1
788  puts( "Skipping import of base64-encoded data on EBCDIC system.\n" );
789  return( TRUE );
790 #endif /* EBCDIC system */
791 
792  for( i = 1; i <= 1; i++ )
793  if( !certChainImport( i, TRUE ) )
794  return( FALSE );
795  return( TRUE );
796  }
797 
798 static int miscImport( const char *fileName, const char *description )
799  {
800  CRYPT_CERTIFICATE cryptCert;
801  FILE *filePtr;
802  BYTE buffer[ BUFFER_SIZE ];
803  int count, status;
804 
805  if( ( filePtr = fopen( fileName, "rb" ) ) == NULL )
806  {
807  printf( "Couldn't find file for %s key import test.\n",
808  description );
809  return( FALSE );
810  }
811  count = fread( buffer, 1, BUFFER_SIZE, filePtr );
812  fclose( filePtr );
813 
814  /* Import the object. Since this isn't a certificate we can't do much
815  more with it than this - this is only used to test the low-level
816  code and needs to be run inside a debugger, since the call always
817  fails (the data being imported isn't a certificate) */
818  status = cryptImportCert( buffer, count, CRYPT_UNUSED,
819  &cryptCert );
820  if( cryptStatusError( status ) && status != CRYPT_ERROR_BADDATA )
821  {
822  printf( "cryptImportCert() for %s key failed with error code %d, "
823  "line %d.\n", description, status, __LINE__ );
824  return( FALSE );
825  }
826 
827  /* Clean up */
828  cryptDestroyCert( cryptCert );
829  return( TRUE );
830  }
831 
832 int testMiscImport( void )
833  {
834  BYTE buffer[ BUFFER_SIZE ];
835  int i;
836 
837  puts( "Testing base64-encoded SSH/PGP key import..." );
838  for( i = 1; i <= 2; i++ )
839  {
841  if( !miscImport( buffer, "SSH" ) )
842  return( FALSE );
843  }
844  for( i = 1; i <= 3; i++ )
845  {
847  if( !miscImport( buffer, "PGP" ) )
848  return( FALSE );
849  }
850  puts( "Import succeeded.\n" );
851  return( TRUE );
852  }
853 
854 /* Test handling of certs that chain by DN but not by keyID */
855 
856 int testNonchainCert( void )
857  {
858  /* The EE certificate expired in November 2007 so unfortunately we can't
859  perform this test any more until we can obtain further broken
860  certs from DigiCert */
861 #if 0
862  CRYPT_CERTIFICATE cryptLeafCert, cryptCACert;
863  int value, status;
864 
865  puts( "Testing handling of incorrectly chained certs..." );
866 
867  /* Since this test requires the use of attributes that aren't decoded at
868  the default compliance level, we have to raise it a notch to make sure
869  that we get the certificate attributes necessary to sort out the
870  mess */
872  &value );
876 
877  /* Get the EE and incorrectly chained CA certs */
878  status = importCertFile( &cryptLeafCert, NOCHAIN_EE_FILE );
879  if( cryptStatusOK( status ) )
880  status = importCertFile( &cryptCACert, NOCHAIN_CA_FILE );
881  if( cryptStatusError( status ) )
882  return( FALSE );
883 
885  value );
886 
887  /* Check the EE certificate using the apparently-correct but actually
888  incorrect CA certificate and make sure that we get the correct error
889  message */
890  status = cryptCheckCert( cryptLeafCert, cryptCACert );
891  if( status != CRYPT_ERROR_SIGNATURE )
892  {
893  printf( "Sig.check of incorrectly chained certificate returned %d, "
894  "should have been %d, line %d.\n", status,
895  CRYPT_ERROR_SIGNATURE, __LINE__ );
896  return( FALSE );
897  }
898 
899  /* Clean up */
900  cryptDestroyCert( cryptLeafCert );
901  cryptDestroyCert( cryptCACert );
902 
903  puts( "Handling of incorrectly chained certs succeeded.\n" );
904 #endif /* 0 */
905  return( TRUE );
906  }
907 
908 /* Test certificate handling at various levels of compliance */
909 
911  {
912  CRYPT_CERTIFICATE cryptCert, cryptCaCert = DUMMY_INIT;
913  FILE *filePtr;
914  BYTE buffer[ BUFFER_SIZE ];
915  int count, value, status;
916 
918  &value );
919 
920  /* Test import of a broken certificate. The brokenness is an invalid
921  authorityKeyIdentifier which is processed at level
922  CRYPT_COMPLIANCELEVEL_PKIX_PARTIAL and above, so first we try it in
923  CRYPT_COMPLIANCELEVEL_PKIX_PARTIAL mode, which should fail, and then
924  again in oblivious mode, which should succeed */
925  printf( "Testing certificate handling at various compliance levels "
926  "(current = %d)...\n", value );
927  if( ( filePtr = fopen( convertFileName( BROKEN_CERT_FILE ), "rb" ) ) == NULL )
928  {
929  puts( "Couldn't certificate for import test." );
930  return( FALSE );
931  }
932  count = fread( buffer, 1, BUFFER_SIZE, filePtr );
933  fclose( filePtr );
935  {
936  status = cryptSetAttribute( CRYPT_UNUSED,
939  if( status == CRYPT_ERROR_PARAM3 )
940  {
941  puts( "(Couldn't set compliance level to "
942  "CRYPT_COMPLIANCELEVEL_PKIX_PARTIAL, probably\n because "
943  "cryptlib has been configured to not use this level, "
944  "skipping this\n test...)" );
945  }
946  else
947  {
948  status = cryptImportCert( buffer, count, CRYPT_UNUSED,
949  &cryptCert );
950  }
951  if( cryptStatusOK( status ) )
952  {
953  /* Import in CRYPT_COMPLIANCELEVEL_PKIX_PARTIAL mode should
954  fail */
957  printf( "cryptImportCert() of broken certificate succeeded when "
958  "it should have failed, line %d.\n", __LINE__ );
959  return( FALSE );
960  }
961  }
964  status = cryptImportCert( buffer, count, CRYPT_UNUSED,
965  &cryptCert );
967  value );
968  if( cryptStatusError( status ) )
969  {
970  /* Import in standard mode should succeed */
971  return( handleCertImportError( status, __LINE__ ) );
972  }
973 
974  /* Print information on what we've got. This should only print info for
975  the two basic extensions that are handled in oblivious mode */
976  if( !printCertInfo( cryptCert ) )
977  return( FALSE );
978  cryptDestroyCert( cryptCert );
979 
980  /* Test checking of an expired certificate using a broken CA certificate
981  in oblivious mode (this checks chaining and the signature, but little
982  else) */
983  status = importCertFile( &cryptCert, BROKEN_USER_CERT_FILE );
984  if( cryptStatusOK( status ) )
985  status = importCertFile( &cryptCaCert, BROKEN_CA_CERT_FILE );
986  if( cryptStatusError( status ) )
987  return( handleCertImportError( status, __LINE__ ) );
988  status = cryptCheckCert( cryptCert, cryptCaCert );
989  if( cryptStatusOK( status ) )
990  {
991  /* Checking in normal mode should fail */
992  printf( "cryptCheckCert() of broken certificate succeeded when it "
993  "should have failed, line %d.\n", __LINE__ );
994  return( FALSE );
995  }
998  status = cryptCheckCert( cryptCert, cryptCaCert );
1000  value );
1001  if( cryptStatusError( status ) )
1002  {
1003  /* Checking in oblivious mode should succeed */
1004  printf( "cryptCheckCert() of broken certificate failed when it "
1005  "should have succeeded, line %d.\n", __LINE__ );
1006  return( FALSE );
1007  }
1008  cryptDestroyCert( cryptCaCert );
1009  cryptDestroyCert( cryptCert );
1010 
1011  /* Clean up */
1012  puts( "Certificate handling at different compliance levels succeeded.\n" );
1013  return( TRUE );
1014  }
1015 
1016 /****************************************************************************
1017 * *
1018 * NIST Path-processing Test *
1019 * *
1020 ****************************************************************************/
1021 
1022 /* Test path processing using the NIST PKI test suite. This doesn't run all
1023  of the tests since some are somewhat redundant (e.g. path length
1024  constraints ending at certificate n in a chain vs.cert n+1 in a chain
1025  where both are well short of the constraint length) or require complex
1026  additional processing (e.g. CRL fetches) which it's difficult to
1027  automate */
1028 
1029 typedef struct {
1030  const int fileMajor, fileMinor; /* Major and minor number of file */
1031  const BOOLEAN isValid; /* Whether path is valid */
1032  const BOOLEAN policyOptional; /* Whether explicit policy optional */
1033  } PATH_TEST_INFO;
1034 
1035 static const PATH_TEST_INFO FAR_BSS pathTestInfo[] = {
1036  /* Signature verification */
1037  /* 0 */ { 1, 1, TRUE },
1038  /* 1 */ { 1, 2, FALSE },
1039  /* 2 */ { 1, 3, FALSE },
1040  /* 3 */ { 1, 4, TRUE },
1041  /* 4 */ { 1, 6, FALSE },
1042 
1043  /* Validity periods */
1044  /* 5 */ { 2, 1, FALSE },
1045  /* 6 */ { 2, 2, FALSE },
1046  /* The second certificate in test 4.2.3 has a validFrom date of 1950
1047  which cryptlib rejects on import as being not even remotely valid (it
1048  can't even be represented in the ANSI/ISO C date format). Supposedly
1049  half-century-old certs are symptomatic of severely broken software so
1050  rejecting this certificate is justified */
1051 /* ** X ** { 2, 3, TRUE }, */
1052  /* 7 */ { 2, 4, TRUE },
1053  /* 8 */ { 2, 5, FALSE },
1054  /* 9 */ { 2, 6, FALSE },
1055  /* 10 */ { 2, 7, FALSE },
1056  /* 11 */ { 2, 8, TRUE },
1057 
1058  /* Name chaining */
1059  /* 12 */ { 3, 1, FALSE },
1060  /* 13 */ { 3, 2, FALSE },
1061  /* 14 */ { 3, 6, TRUE },
1062  /* 15 */ { 3, 7, TRUE },
1063  /* 16 */ { 3, 8, TRUE },
1064  /* 17 */ { 3, 9, TRUE },
1065 
1066  /* 4 = CRLs */
1067 
1068  /* oldWithNew / newWithOld */
1069  /* 18 */ { 5, 1, TRUE },
1070  /* 19 */ { 5, 3, TRUE },
1071 
1072  /* Basic constraints */
1073  /* 20 */ { 6, 1, FALSE },
1074  /* 21 */ { 6, 2, FALSE },
1075  /* 22 */ { 6, 3, FALSE },
1076  /* 23 */ { 6, 4, TRUE },
1077  /* 24 */ { 6, 5, FALSE },
1078  /* 25 */ { 6, 6, FALSE },
1079  /* 26 */ { 6, 7, TRUE },
1080  /* The second-to-last certificate in the path sets a pathLenConstraint of
1081  zero with the next certificate being a CA certificate (there's no EE
1082  certificate present). cryptlib treats this as invalid since it can
1083  never lead to a valid path once the EE certificate is added */
1084  /* 27 */ { 6, 8, FALSE /* TRUE */ },
1085  /* 28 */ { 6, 9, FALSE },
1086  /* 29 */ { 6, 10, FALSE },
1087 
1088  /* 30 */ { 6, 11, FALSE },
1089  /* 31 */ { 6, 12, FALSE },
1090  /* 32 */ { 6, 13, TRUE },
1091  /* This has the same problem as 4.6.8 */
1092  /* 33 */ { 6, 14, FALSE /* TRUE */ },
1093  /* The following are 4.5.x-style oldWithNew / newWithOld but with path
1094  constraints */
1095  /* 34 */ { 6, 15, TRUE },
1096  /* 35 */ { 6, 16, FALSE },
1097  /* 36 */ { 6, 17, TRUE },
1098 
1099  /* Key usage */
1100  /* 37 */ { 7, 1, FALSE },
1101  /* 38 */ { 7, 2, FALSE },
1102  /* 39 */ { 7, 3, TRUE },
1103 
1104  /* Policies */
1105  /* 40 */ { 8, 1, TRUE },
1106  /* 41 */ { 8, 2, TRUE },
1107  /* The first certificate asserts a policy that differs from that of all
1108  other certificates in the path. If no explicit policy is required
1109  (by setting CRYPT_OPTION_REQUIREPOLICY to FALSE) it will verify,
1110  otherwise it won't */
1111  /* 42 */ { 8, 3, TRUE, TRUE }, /* Policy optional */
1112  /* 43 */ { 8, 3, FALSE },
1113  /* 44 */ { 8, 4, FALSE },
1114  /* 45 */ { 8, 5, FALSE },
1115  /* 46 */ { 8, 6, TRUE },
1116  /* The false -> true changes below (4.8.7, 4.8.8, 4.8.9) occur because
1117  cryptlib takes its initial policy from the first CA certificate with
1118  a policy that it finds. This is due to real-world issues where re-
1119  parented certificate chains due to re-sold CA root keys end up with
1120  different policies in the root and the next-level-down pseudo-root
1121  and problems where the root is an extension-less X.509v1 certificate.
1122  The same issue crops up in the 4.10.* / 4.11.* tests further down */
1123  /* 47 */ { 8, 7, /* FALSE */ TRUE },
1124  /* 48 */ { 8, 8, /* FALSE */ TRUE },
1125  /* 49 */ { 8, 9, /* FALSE */ TRUE },
1126  /* 50 */ { 8, 10, TRUE },
1127  /* 51 */ { 8, 11, TRUE },
1128  /* 52 */ { 8, 12, FALSE },
1129  /* 53 */ { 8, 13, TRUE },
1130  /* 54 */ { 8, 14, TRUE },
1131  /* 55 */ { 8, 15, TRUE },
1132  /* 56 */ { 8, 20, TRUE },
1133 
1134  /* Policy constraints. For these tests policy handling is dictated by
1135  policy constraints so we don't require explicit policies */
1136  /* 57 */ { 9, 1, TRUE },
1137  /* 58 */ { 9, 2, TRUE, TRUE },
1138  /* The NIST test value for this one is wrong. RFC 3280 section 4.2.1.12
1139  says:
1140 
1141  If the requireExplicitPolicy field is present, the value of
1142  requireExplicitPolicy indicates the number of additional
1143  certificates that may appear in the path before an explicit policy
1144  is required for the entire path. When an explicit policy is
1145  required, it is necessary for all certificates in the path to
1146  contain an acceptable policy identifier in the certificate policies
1147  extension.
1148 
1149  Test 4.9.3 has requireExplicitPolicy = 4 in a chain of 4 certs for
1150  which the last one has no policy. NIST claims this shouldn't
1151  validate, which is incorrect */
1152  /* 59 */ { 9, 3, TRUE /* FALSE */, TRUE },
1153  /* 60 */ { 9, 4, TRUE, TRUE },
1154  /* 61 */ { 9, 5, FALSE, TRUE },
1155  /* 62 */ { 9, 6, TRUE, TRUE },
1156  /* 63 */ { 9, 7, FALSE, TRUE },
1157  /* 64 */ { 9, 8, FALSE, TRUE },
1158 
1159  /* 10, 11 = Policy mappings. The false -> true changes below (4.10.2,
1160  4.10.4) occur because cryptlib takes its initial policy from the
1161  first CA certificate with a policy that it finds. This is due to
1162  real-world issues where re-parented certificate chains due to re-sold
1163  CA root keys end up with different policies in the root and the next-
1164  level-down pseudo-root and problems where the root is an extension-
1165  less X.509v1 certificate */
1166  /* 65 */ { 10, 1, TRUE },
1167  /* 66 */ { 10, 2, /* FALSE */ TRUE },
1168  /* 67 */ { 10, 3, TRUE },
1169  /* 68 */ { 10, 4, /* FALSE */ TRUE },
1170  /* 69 */ { 10, 5, TRUE },
1171  /* 70 */ { 10, 6, TRUE },
1172  /* 71 */ { 10, 7, FALSE },
1173  /* 72 */ { 10, 8, FALSE },
1174  /* 73 */ { 10, 9, TRUE },
1175  /* The test for 4.10.10 is a special case because it contains the
1176  retroactively triggered requireExplicitPolicy extension, see the long
1177  comment in chk_chn.c for a discussion of this, for now we just
1178  disable the check by recording it as a value-true check because even
1179  the standards committee can't explain why it does what it does */
1180  /* 74 */ { 10, 10, /* FALSE */ TRUE },
1181  /* 75 */ { 10, 11, TRUE },
1182  /* 76 */ { 10, 12, TRUE },
1183  /* 77 */ { 10, 13, TRUE },
1184  /* 78 */ { 10, 14, TRUE },
1185 
1186  /* Policy inhibitPolicy. The false -> true changes below (4.11.1) are
1187  as for the 10.x tests */
1188  /* 79 */ { 11, 1, /* FALSE */ TRUE },
1189  /* The NIST test value for 4.11.2 is wrong, the top-level CA
1190  certificate sets inhibitPolicyMapping to 1, the mid-level CA
1191  certificate maps policy 1 to policy 3, and the EE certificte asserts
1192  policy 3, however at this point inhibitPolicyMapping is in effect
1193  and policy 3 is no longer valid */
1194  /* 80 */ { 11, 2, /* TRUE */ FALSE },
1195  /* 81 */ { 11, 3, FALSE },
1196  /* The NIST test value for 4.11.4 is wrong for the same reason as for
1197  4.11.2, except that the point of failure is a second sub-CA rather
1198  than the EE */
1199  /* 82 */ { 11, 4, /* TRUE */ FALSE },
1200  /* 83 */ { 11, 5, FALSE },
1201  /* 84 */ { 11, 6, FALSE },
1202  /* The NIST test value for 4.11.7 is wrong for the same reason as for
1203  4.11.2, except that the mapping is from policy 1 to policy 2 instead
1204  of policy 3 */
1205  /* 85 */ { 11, 7, /* TRUE */ FALSE },
1206  /* 86 */ { 11, 8, FALSE },
1207  /* 87 */ { 11, 9, FALSE },
1208  /* 88 */ { 11, 10, FALSE },
1209  /* 89 */ { 11, 11, FALSE },
1210 
1211  /* Policy inhibitAny */
1212  /* 90 */ { 12, 1, FALSE },
1213  /* 91 */ { 12, 2, TRUE },
1214  /* 92 */ { 12, 3, TRUE },
1215  /* 93 */ { 12, 4, FALSE },
1216  /* 94 */ { 12, 5, FALSE },
1217  /* 95 */ { 12, 6, FALSE },
1218  /* The NIST test results for 4.12.7 and 4.12.9 are wrong or more
1219  specifically the PKIX spec is wrong, contradicting itself in the body
1220  of the spec and the path-processing pseudocode in that there's no
1221  path-kludge exception for policy constraints in the body but there is
1222  one in the pseudocode. Since these chains contain path-kludge certs
1223  the paths are invalid - they would only be valid if there was a path-
1224  kludge exception for inhibitAnyPolicy. Note that 4.9.7 and 4.9.8
1225  have the same conditions for requireExplicitPolicy but this time the
1226  NIST test results go the other way. So although the PKIX spec is
1227  wrong the NIST test is also wrong in that it applies an inconsistent
1228  interpretation of the contradictions in the PKIX spec */
1229  /* 96 */ { 12, 7, FALSE /* TRUE */ },
1230  /* 97 */ { 12, 8, FALSE },
1231  /* 98 */ { 12, 9, FALSE /* TRUE */ },
1232  /* 99 */ { 12, 10, FALSE },
1233 
1234  /* Name constraints */
1235  /* 100 */ { 13, 1, TRUE },
1236  /* 101 */ { 13, 2, FALSE },
1237  /* 102 */ { 13, 3, FALSE },
1238  /* 103 */ { 13, 4, TRUE },
1239  /* 104 */ { 13, 5, TRUE },
1240  /* 105 */ { 13, 6, TRUE },
1241  /* 106 */ { 13, 7, FALSE },
1242  /* 107 */ { 13, 8, FALSE },
1243  /* 108 */ { 13, 9, FALSE },
1244  /* 109 */ { 13, 10, FALSE },
1245  /* 110 */ { 13, 11, TRUE },
1246  /* 111 */ { 13, 12, FALSE },
1247  /* 112 */ { 13, 13, FALSE },
1248  /* 113 */ { 13, 14, TRUE },
1249  /* 114 */ { 13, 15, FALSE },
1250  /* 115 */ { 13, 16, FALSE },
1251  /* 116 */ { 13, 17, FALSE },
1252  /* 117 */ { 13, 18, TRUE },
1253  /* 118 */ { 13, 19, TRUE },
1254  /* 119 */ { 13, 20, FALSE },
1255  /* 120 */ { 13, 21, TRUE },
1256  /* 121 */ { 13, 22, FALSE },
1257  /* 122 */ { 13, 23, TRUE },
1258  /* 123 */ { 13, 24, FALSE },
1259  /* 124 */ { 13, 25, TRUE },
1260  /* 125 */ { 13, 26, FALSE },
1261  /* 126 */ { 13, 27, TRUE },
1262  /* 127 */ { 13, 28, FALSE },
1263  /* 188 */ { 13, 29, FALSE },
1264  /* 129 */ { 13, 30, TRUE },
1265  /* 130 */ { 13, 31, FALSE },
1266  /* 131 */ { 13, 32, TRUE },
1267  /* 132 */ { 13, 33, FALSE },
1268  /* 133 */ { 13, 34, TRUE },
1269  /* 134 */ { 13, 35, FALSE },
1270  /* 135 */ { 13, 36, TRUE },
1271  /* 136 */ { 13, 37, FALSE },
1272  /* The NIST test results for 4.13.38 are wrong. PKIX section 4.2.1.11
1273  says:
1274 
1275  DNS name restrictions are expressed as foo.bar.com. Any DNS name
1276  that can be constructed by simply adding to the left hand side of
1277  the name satisfies the name constraint. For example,
1278  www.foo.bar.com would satisfy the constraint but foo1.bar.com would
1279  not.
1280 
1281  The permitted subtree is testcertificates.gov and the altName is
1282  mytestcertificates.gov which satisfies the above rule so the path
1283  should be valid and not invalid */
1284  /* 137 */ { 13, 38, TRUE /* FALSE */ },
1285 
1286  /* 14, 15 = CRLs */
1287 
1288  /* Private certificate extensions */
1289  /* 138 */ { 16, 1, TRUE },
1290  /* 139 */ { 16, 2, FALSE },
1291  { 0, 0 }
1292  };
1293 
1294 static int testPath( const PATH_TEST_INFO *pathInfo )
1295  {
1296  CRYPT_CERTIFICATE cryptCertPath;
1297  char pathName[ 64 ];
1298  int pathNo, requirePolicy, status;
1299 
1300  /* Convert the composite path info into a single number used for fetching
1301  the corresponding data file */
1302  sprintf( pathName, "4%d%d", pathInfo->fileMajor, pathInfo->fileMinor );
1303  pathNo = atoi( pathName );
1304 
1305  /* Test the path */
1306  sprintf( pathName, "4.%d.%d", pathInfo->fileMajor, pathInfo->fileMinor );
1307  printf( " Path %s%s...", pathName, pathInfo->policyOptional ? \
1308  " without explicit policy" : "" );
1309  status = importCertFromTemplate( &cryptCertPath,
1310  PATHTEST_FILE_TEMPLATE, pathNo );
1311  if( cryptStatusError( status ) )
1312  {
1313  printf( "Certificate import for test path %s failed, status %d, "
1314  "line %d.\n", pathName, status, __LINE__ );
1315  return( FALSE );
1316  }
1317  if( pathInfo->policyOptional )
1318  {
1319  /* By default we require policy chaining, for some tests we can turn
1320  this off to check non-explict policy processing */
1322  &requirePolicy );
1323  assert( requirePolicy != FALSE );
1325  FALSE );
1326  }
1327  status = cryptCheckCert( cryptCertPath, CRYPT_UNUSED );
1328  if( pathInfo->policyOptional )
1329  {
1331  requirePolicy );
1332  }
1333  if( pathInfo->isValid )
1334  {
1335  if( cryptStatusError( status ) )
1336  {
1337  puts( " didn't verify even though it should be valid." );
1338  return( attrErrorExit( cryptCertPath, "cryptCheckCert()",
1339  status, __LINE__ ) );
1340  }
1341  }
1342  else
1343  {
1344  if( cryptStatusOK( status ) )
1345  {
1346  puts( " verified even though it should have failed." );
1347  return( FALSE );
1348  }
1349  }
1350  puts( " succeeded." );
1351  cryptDestroyCert( cryptCertPath );
1352 
1353  return( TRUE );
1354  }
1355 
1357  {
1358  CRYPT_CERTIFICATE cryptRootCert;
1359  int certTrust = DUMMY_INIT, complianceLevel, i, status;
1360 
1361  puts( "Testing path processing..." );
1362 
1363  /* Get the root certificate and make it implicitly trusted and crank the
1364  compliance level up to maximum, since we're going to be testing some
1365  pretty obscure extensions */
1366  status = importCertFromTemplate( &cryptRootCert,
1368  if( cryptStatusOK( status ) )
1369  status = setRootTrust( cryptRootCert, &certTrust, 1 );
1370  if( cryptStatusError( status ) )
1371  {
1372  printf( "Couldn't create trusted root certificate for path "
1373  "processing, line %d.\n", __LINE__ );
1374  return( FALSE );
1375  }
1377  &complianceLevel );
1378  status = cryptSetAttribute( CRYPT_UNUSED,
1381  if( cryptStatusError( status ) )
1382  {
1383  printf( "Couldn't set compliance level to "
1384  "CRYPT_COMPLIANCELEVEL_PKIX_FULL, line %d.\nThis may be "
1385  "because cryptlib has been configured not to run at this "
1386  "level.\n", __LINE__ );
1387  return( FALSE );
1388  }
1389 
1390  /* Process each certificate path and make sure that it succeeds or fails
1391  as required */
1392  for( i = 0; pathTestInfo[ i ].fileMajor != 0; i++ )
1393  {
1394  if( !testPath( &pathTestInfo[ i ] ) )
1395  break;
1396  }
1397  setRootTrust( cryptRootCert, NULL, certTrust );
1398  cryptDestroyCert( cryptRootCert );
1400  complianceLevel );
1401  if( pathTestInfo[ i ].fileMajor )
1402  return( FALSE );
1403 
1404  puts( "Path processing succeeded." );
1405  return( TRUE );
1406  }
1407 
1408 /****************************************************************************
1409 * *
1410 * Miscellaneous Tests *
1411 * *
1412 ****************************************************************************/
1413 
1414 /* Test handling of invalid PKCS #1 padding in certificate signatures. Note
1415  that running this test properly requires disabling the PKCS#1 padding
1416  format check in decodePKCS1() in mechs/mech_sig.c since the signatures
1417  have such an obviously dodgy format that they don't even make it past the
1418  basic padding sanity check */
1419 
1420 int testPKCS1Padding( void )
1421  {
1422  CRYPT_CERTIFICATE cryptCert;
1423  int i, complianceValue, status;
1424 
1425  puts( "Testing invalid PKCS #1 padding handling..." );
1426 
1427  /* The test certs don't have a keyUsage present in a CA certificate so
1428  we have to lower the compliance level to be able to get past this
1429  check to the signatures */
1431  &complianceValue );
1434  for( i = 1; i <= 11; i++ )
1435  {
1436  status = importCertFromTemplate( &cryptCert, PADTEST_FILE_TEMPLATE,
1437  i );
1438  if( cryptStatusError( status ) )
1439  {
1440  printf( "Couldn't import certificate for PKCS #1 padding check, "
1441  "status %d, line %d.\n", status, __LINE__ );
1442  return( FALSE );
1443  }
1444  status = cryptCheckCert( cryptCert, CRYPT_UNUSED );
1445  if( cryptStatusOK( status ) )
1446  {
1447  printf( "Certificate with bad PKSC #1 padding verified, should "
1448  "have failed, line %d.\n", __LINE__ );
1449  return( FALSE );
1450  }
1451  cryptDestroyCert( cryptCert );
1452  }
1454  complianceValue );
1455 
1456  puts( "Padding handling succeeded (all certs rejected).\n" );
1457  return( TRUE );
1458  }
1459 
1460 /* Generic test routines used for debugging. These are only meant to be
1461  used interactively, and throw exceptions rather than returning status
1462  values */
1463 
1464 void xxxCertImport( const char *fileName )
1465  {
1466  CRYPT_CERTIFICATE cryptCert;
1467  FILE *filePtr;
1468  BYTE buffer[ BUFFER_SIZE ], *bufPtr = buffer;
1469  long length, count;
1470  int status;
1471 
1472  filePtr = fopen( fileName, "rb" );
1473  assert( filePtr != NULL );
1474  fseek( filePtr, 0L, SEEK_END );
1475  length = ftell( filePtr );
1476  fseek( filePtr, 0L, SEEK_SET );
1477  if( length > BUFFER_SIZE )
1478  {
1479  bufPtr = malloc( length );
1480  assert( bufPtr != NULL );
1481  }
1482  count = fread( bufPtr, 1, length, filePtr );
1483  assert( count == length );
1484  fclose( filePtr );
1485  status = cryptImportCert( bufPtr, count, CRYPT_UNUSED, &cryptCert );
1486  assert( cryptStatusOK( status ) );
1487  if( bufPtr != buffer )
1488  free( bufPtr );
1489  printCertInfo( cryptCert );
1490  cryptCheckCert( cryptCert, CRYPT_UNUSED ); /* Opportunistic only */
1491  cryptDestroyCert( cryptCert );
1492  }
1493 
1494 void xxxCertCheck( const C_STR certFileName, const C_STR caFileNameOpt )
1495  {
1496  CRYPT_CERTIFICATE cryptCert, cryptCaCert;
1497  int status;
1498 
1499  status = importCertFile( &cryptCert, certFileName );
1500  assert( cryptStatusOK( status ) );
1501  if( caFileNameOpt == NULL )
1502  cryptCaCert = CRYPT_UNUSED;
1503  else
1504  {
1505  status = importCertFile( &cryptCaCert, caFileNameOpt );
1506  assert( cryptStatusOK( status ) );
1507  }
1508  status = cryptCheckCert( cryptCert, cryptCaCert );
1509  if( cryptStatusError( status ) )
1510  printErrorAttributeInfo( cryptCert );
1511  assert( cryptStatusOK( status ) );
1512  cryptDestroyCert( cryptCert );
1513  cryptDestroyCert( cryptCaCert );
1514  }