📄 certimp.c
字号:
"failed, status = %d, line %d.\n", status, __LINE__ );
return( FALSE );
}
status = cryptCheckCert( cryptCertChain, CRYPT_UNUSED );
if( status == CRYPT_ERROR_INVALID )
cryptGetAttribute( cryptCertChain, CRYPT_ATTRIBUTE_ERRORLOCUS,
&errorLocus );
}
if( errorLocus == CRYPT_CERTINFO_VALIDTO )
{
/* One (or more) certs in the chain have expired, try again with the
compliance level wound down to nothing */
puts( "\nThe certificate chain didn't verify because one or more "
"certificates in it\nhave expired. Trying again in oblivious "
"mode..." );
cryptGetAttribute( CRYPT_UNUSED, CRYPT_OPTION_CERT_COMPLIANCELEVEL,
&complianceValue );
cryptSetAttribute( CRYPT_UNUSED, CRYPT_OPTION_CERT_COMPLIANCELEVEL,
CRYPT_COMPLIANCELEVEL_OBLIVIOUS );
status = cryptCheckCert( cryptCertChain, CRYPT_UNUSED );
}
/* If we changed settings, restore their original values */
if( trustValue != CRYPT_UNUSED )
setRootTrust( cryptCertChain, NULL, trustValue );
if( complianceValue != CRYPT_UNUSED )
cryptSetAttribute( CRYPT_UNUSED, CRYPT_OPTION_CERT_COMPLIANCELEVEL,
complianceValue );
/* Some old certs use deprecated or now-broken algorithms which will
produce a CRYPT_ERROR_NOTAVAIL if we try and verify the signature,
treat this as a special case */
if( certNo == 2 && status == CRYPT_ERROR_NOTAVAIL )
{
puts( "\nWarning: The hash/signature algorithm required to verify "
"this certificate\n isn't enabled in this build of "
"cryptlib, can't verify the cert\n signature." );
return( TRUE );
}
/* If the lowered-limits check still didn't work, it's an error */
if( cryptStatusError( status ) )
{
putchar( '\n' );
return( attrErrorExit( cryptCertChain, "cryptCheckCert()", status,
__LINE__ ) );
}
puts( "signatures verified." );
return( TRUE );
}
static int certChainImport( const int certNo, const BOOLEAN isBase64 )
{
CRYPT_CERTIFICATE cryptCertChain;
FILE *filePtr;
BYTE buffer[ BUFFER_SIZE ];
int count, status;
printf( "Testing %scert chain #%d import...\n",
isBase64 ? "base64 " : "", certNo );
filenameFromTemplate( buffer, isBase64 ? BASE64CERTCHAIN_FILE_TEMPLATE : \
CERTCHAIN_FILE_TEMPLATE, certNo );
if( ( filePtr = fopen( buffer, "rb" ) ) == NULL )
{
puts( "Couldn't find certificate chain file for import test." );
return( FALSE );
}
count = fread( buffer, 1, BUFFER_SIZE, filePtr );
fclose( filePtr );
if( count == BUFFER_SIZE )
{
puts( "The certificate buffer size is too small for the certificate "
"chain. To fix\nthis, increase the BUFFER_SIZE value in "
"test/testcert.c and recompile the code." );
return( TRUE ); /* Skip this test and continue */
}
printf( "Certificate chain has size %d bytes.\n", count );
/* Import the certificate chain. This assumes that the default certs are
installed as trusted certs, which is required for cryptCheckCert() */
status = cryptImportCert( buffer, count, CRYPT_UNUSED,
&cryptCertChain );
if( cryptStatusError( status ) )
{
/* If we failed on the RSA e=3 cert, this is a valid result */
if( certNo == 3 && status == CRYPT_ERROR_BADDATA )
{
printf( "Import of certificate with invalid e=3 key failed, "
"line %d.\n", __LINE__ );
puts( " (This is the correct result for this test).\n" );
return( TRUE );
}
printf( "cryptImportCert() failed with error code %d, line %d.\n",
status, __LINE__ );
return( FALSE );
}
if( certNo == 3 )
{
printf( "Import of certificate with invalid e=3 key succeeded when "
"it should have\n failed, line %d.\n", __LINE__ );
return( FALSE );
}
printf( "Checking signatures... " );
status = cryptCheckCert( cryptCertChain, CRYPT_UNUSED );
if( cryptStatusError( status ) && \
!handleCertChainError( cryptCertChain, certNo, status ) )
return( FALSE );
puts( "signatures verified." );
/* Display info on each cert in the chain */
if( !printCertChainInfo( cryptCertChain ) )
return( FALSE );
/* Clean up */
cryptDestroyCert( cryptCertChain );
puts( "Certificate chain import succeeded.\n" );
return( TRUE );
}
int testCertChainImport( void )
{
int i;
for( i = 1; i <= 3; i++ )
{
if( !certChainImport( i, FALSE ) )
return( FALSE );
}
return( TRUE );
}
int testOCSPImport( void )
{
CRYPT_CERTIFICATE cryptCert, cryptResponderCert;
FILE *filePtr;
BYTE buffer[ BUFFER_SIZE ];
int count, status;
if( ( filePtr = fopen( convertFileName( OCSP_OK_FILE ), "rb" ) ) == NULL )
{
puts( "Couldn't find OCSP OK response file for import test." );
return( FALSE );
}
puts( "Testing OCSP OK response import..." );
count = fread( buffer, 1, BUFFER_SIZE, filePtr );
fclose( filePtr );
printf( "OCSP OK response has size %d bytes.\n", count );
/* Import the OCSP OK response. Because of the choose-your-own-trust-
model status of the OCSP RFC we have to supply our own signature
check cert to verify the response */
status = cryptImportCert( buffer, count, CRYPT_UNUSED,
&cryptCert );
if( cryptStatusError( status ) )
{
printf( "cryptImportCert() failed with error code %d, line %d.\n",
status, __LINE__ );
return( FALSE );
}
printf( "Checking signature... " );
status = importCertFile( &cryptResponderCert, OCSP_CA_FILE );
if( cryptStatusOK( status ) )
{
status = cryptCheckCert( cryptCert, cryptResponderCert );
cryptDestroyCert( cryptResponderCert );
}
if( cryptStatusError( status ) )
return( attrErrorExit( cryptCert, "cryptCheckCert()", status,
__LINE__ ) );
puts( "signatures verified." );
/* Print information on what we've got */
if( !printCertInfo( cryptCert ) )
return( FALSE );
cryptDestroyCert( cryptCert );
/* Now import the OCSP revoked response. This has a different CA cert
than the OK response, to keep things simple we don't bother with a
sig check for this one */
puts( "Testing OCSP revoked response import..." );
if( ( filePtr = fopen( convertFileName( OCSP_REV_FILE ), "rb" ) ) == NULL )
{
puts( "Couldn't find OCSP revoked response file for import test." );
return( FALSE );
}
count = fread( buffer, 1, BUFFER_SIZE, filePtr );
fclose( filePtr );
printf( "OCSP revoked response has size %d bytes.\n", count );
status = cryptImportCert( buffer, count, CRYPT_UNUSED,
&cryptCert );
if( cryptStatusError( status ) )
{
printf( "cryptImportCert() failed with error code %d, line %d.\n",
status, __LINE__ );
return( FALSE );
}
/* Print information on what we've got */
if( !printCertInfo( cryptCert ) )
return( FALSE );
/* Clean up */
cryptDestroyCert( cryptCert );
puts( "OCSP import succeeded.\n" );
return( TRUE );
}
int testBase64CertImport( void )
{
int i;
/* If this is an EBCDIC system, we can't (easily) import the base64-
encoded cert without complex calisthenics to handle the different
character sets */
#if 'A' == 0xC1
puts( "Skipping import of base64-encoded data on EBCDIC system.\n" );
return( TRUE );
#endif /* EBCDIC system */
for( i = 1; i <= 1; i++ )
if( !certImport( i, TRUE ) )
return( FALSE );
return( TRUE );
}
int testBase64CertChainImport( void )
{
int i;
/* If this is an EBCDIC system, we can't (easily) import the base64-
encoded cert without complex calisthenics to handle the different
character sets */
#if 'A' == 0xC1
puts( "Skipping import of base64-encoded data on EBCDIC system.\n" );
return( TRUE );
#endif /* EBCDIC system */
for( i = 1; i <= 1; i++ )
if( !certChainImport( i, TRUE ) )
return( FALSE );
return( TRUE );
}
static int miscImport( const char *fileName, const char *description )
{
CRYPT_CERTIFICATE cryptCert;
FILE *filePtr;
BYTE buffer[ BUFFER_SIZE ];
int count, status;
if( ( filePtr = fopen( fileName, "rb" ) ) == NULL )
{
printf( "Couldn't find file for %s key import test.\n",
description );
return( FALSE );
}
count = fread( buffer, 1, BUFFER_SIZE, filePtr );
fclose( filePtr );
/* Import the object. Since this isn't a certificate we can't do much
more with it than this - this is only used to test the low-level
code and needs to be run inside a debugger, since the call always
fails (the data being imported isn't a certificate) */
status = cryptImportCert( buffer, count, CRYPT_UNUSED,
&cryptCert );
if( cryptStatusError( status ) && status != CRYPT_ERROR_BADDATA )
{
printf( "cryptImportCert() for %s key failed with error code %d, "
"line %d.\n", description, status, __LINE__ );
return( FALSE );
}
/* Clean up */
cryptDestroyCert( cryptCert );
return( TRUE );
}
int testMiscImport( void )
{
BYTE buffer[ BUFFER_SIZE ];
int i;
puts( "Testing base64-encoded SSH/PGP key import..." );
for( i = 1; i <= 2; i++ )
{
filenameFromTemplate( buffer, SSHKEY_FILE_TEMPLATE, i );
if( !miscImport( buffer, "SSH" ) )
return( FALSE );
}
for( i = 1; i <= 3; i++ )
{
filenameFromTemplate( buffer, PGPKEY_FILE_TEMPLATE, i );
if( !miscImport( buffer, "PGP" ) )
return( FALSE );
}
puts( "Import succeeded.\n" );
return( TRUE );
}
/* Test handling of certs that chain by DN but not by keyID */
int testNonchainCert( void )
{
/* The EE cert expired in November 2007 so unfortunately we can't
perform this test any more until we can obtain further broken
certs from DigiCert */
#if 0
CRYPT_CERTIFICATE cryptLeafCert, cryptCACert;
int value, status;
puts( "Testing handling of incorrectly chained certs..." );
/* Since this test requires the use of attributes that aren't decoded at
the default compliance level, we have to raise it a notch to make sure
that we get the cert attributes necessary to sort out the mess */
cryptGetAttribute( CRYPT_UNUSED, CRYPT_OPTION_CERT_COMPLIANCELEVEL,
&value );
if( value < CRYPT_COMPLIANCELEVEL_PKIX_PARTIAL )
cryptSetAttribute( CRYPT_UNUSED, CRYPT_OPTION_CERT_COMPLIANCELEVEL,
CRYPT_COMPLIANCELEVEL_PKIX_PARTIAL );
/* Get the EE and incorrectly chained CA certs */
status = importCertFile( &cryptLeafCert, NOCHAIN_EE_FILE );
if( cryptStatusOK( status ) )
status = importCertFile( &cryptCACert, NOCHAIN_CA_FILE );
if( cryptStatusError( status ) )
return( FALSE );
cryptSetAttribute( CRYPT_UNUSED, CRYPT_OPTION_CERT_COMPLIANCELEVEL,
value );
/* Check the EE cert using the apparently-correct but actually incorrect
CA cert and make sure that we get the correct error message */
status = cryptCheckCert( cryptLeafCert, cryptCACert );
if( status != CRYPT_ERROR_SIGNATURE )
{
printf( "Sig.check of incorrectly chained cert returned %d, should "
"have been %d, line %d.\n", status, CRYPT_ERROR_SIGNATURE,
__LINE__ );
return( FALSE );
}
/* Clean up */
cryptDestroyCert( cryptLeafCert );
cryptDestroyCert( cryptCACert );
puts( "Handling of incorrectly chained certs succeeded.\n" );
#endif /* 0 */
return( TRUE );
}
/* Test cert handling at various levels of compliance */
int testCertComplianceLevel( void )
{
CRYPT_CERTIFICATE cryptCert, cryptCaCert;
FILE *filePtr;
BYTE buffer[ BUFFER_SIZE ];
int count, value, status;
cryptGetAttribute( CRYPT_UNUSED, CRYPT_OPTION_CERT_COMPLIANCELEVEL,
&value );
/* Test import of a broken cert. First we try it in normal mode, then
again in oblivious mode */
printf( "Testing cert handling at various compliance levels "
"(current = %d)...\n", value );
if( ( filePtr = fopen( convertFileName( BROKEN_CERT_FILE ), "rb" ) ) == NULL )
{
puts( "Couldn't certificate for import test." );
return( FALSE );
}
count = fread( buffer, 1, BUFFER_SIZE, filePtr );
fclose( filePtr );
if( value < CRYPT_COMPLIANCELEVEL_PKIX_FULL )
cryptSetAttribute( CRYPT_UNUSED, CRYPT_OPTION_CERT_COMPLIANCELEVEL,
CRYPT_COMPLIANCELEVEL_PKIX_FULL );
status = cryptImportCert( buffer, count, CRYPT_UNUSED,
&cryptCert );
if( cryptStatusOK( status ) )
{
/* Import in normal mode should fail */
cryptSetAttribute( CRYPT_UNUSED, CRYPT_OPTION_CERT_COMPLIANCELEVEL,
value );
printf( "cryptImportCert() of broken cert succeeded when it should "
"have failed, line %d.\n", __LINE__ );
return( FALSE );
}
cryptSetAttribute( CRYPT_UNUSED, CRYPT_OPTION_CERT_COMPLIANCELEVEL,
CRYPT_COMPLIANCELEVEL_STANDARD );
status = cryptImportCert( buffer, count, CRYPT_UNUSED,
&cryptCert );
cryptSetAttribute( CRYPT_UNUSED, CRYPT_OPTION_CERT_COMPLIANCELEVEL,
value );
if( cryptStatusError( status ) )
{
/* Import in reduced-compliance mode should succeed */
printf( "cryptImportCert() failed with error code %d, line %d.\n",
status, __LINE__ );
return( FALSE );
}
/* Print information on what we've got. This should only print info for
the two basic extensions that are handled in oblivious mode */
if( !printCertInfo( cryptCert ) )
return( FALSE );
cryptDestroyCert( cryptCert );
/* Test checking of an expired cert using a broken CA cert in oblivious
mode (this checks chaining and the signature, but little else) */
status = importCertFile( &cryptCert, BROKEN_USER_CERT_FILE );
if( cryptStatusOK( status ) )
status = importCertFile( &cryptCaCert, BROKEN_CA_CERT_FILE );
if( cryptStatusError( status ) )
{
printf( "Cert import failed with error code %d, line %d.\n",
status, __LINE__ );
return( FALSE );
}
status = cryptCheckCert( cryptCert, cryptCaCert );
if( cryptStatusOK( status ) )
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -