⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 certimp.c

📁 cryptlib安全工具包
💻 C
📖 第 1 页 / 共 3 页
字号:
					"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 + -