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

📄 certimp.c

📁 cryptlib安全工具包
💻 C
📖 第 1 页 / 共 3 页
字号:
/****************************************************************************
*																			*
*					cryptlib Certificate Handling Test Routines				*
*						Copyright Peter Gutmann 1997-2005					*
*																			*
****************************************************************************/

#include "cryptlib.h"
#include "test/test.h"

#if defined( __MVS__ ) || defined( __VMCMS__ )
  /* Suspend conversion of literals to ASCII. */
  #pragma convlit( suspend )
#endif /* IBM big iron */
#if defined( __ILEC400__ )
  #pragma convert( 0 )
#endif /* IBM medium iron */

/****************************************************************************
*																			*
*							Certificate Import Routines Test				*
*																			*
****************************************************************************/

/* Test certificate import code */

static BOOLEAN handleCertError( const CRYPT_CERTIFICATE cryptCert, 
								const int certNo, const int errorCode )
	{
	int errorLocus, status;

	printf( "\n" );
	status = cryptGetAttribute( cryptCert, CRYPT_ATTRIBUTE_ERRORLOCUS, 
								&errorLocus );
	if( cryptStatusError( status ) )
		{
		puts( "Couldn't get error locus for certificate check failure." );
		return( FALSE );
		}

	/* 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 == 1 && errorCode == CRYPT_ERROR_NOTAVAIL )
		{
		puts( "Warning: 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 );
		}

	/* Make sure that we don't fail just because the cert that we're using 
	   as a test has expired */
	if( errorLocus == CRYPT_CERTINFO_VALIDTO )
		{
		puts( "Warning: Validity check failed because the certificate has "
			  "expired." );
		return( TRUE );
		}

	/* RegTP CA certs are marked as non-CA certs, report the problem and 
	   continue */
	if( certNo == 4 && errorLocus == CRYPT_CERTINFO_CA )
		{
		puts( "Warning: Validity check failed due to RegTP CA certificate "
			  "incorrectly\n         marked as non-CA certificate." );
		return( TRUE );
		}

	/* Cert #26 is a special-case test cert used to check the ability to 
	   detect invalid PKCS #1 padding */
	if( certNo == 26 )
		{
		puts( "Warning: Certificate contains invalid PKCS #1 padding for "
			  "exponent-3 RSA\n         key, the certificate signature is "
			  "invalid." );
		if( errorCode == CRYPT_ERROR_BADDATA )
			{
			puts( "  (This is the correct result for this test)." );
			return( TRUE );
			}

		/* Not detecting this is an error */
		puts( "  (This should have been detected but wasn't)." );
		return( FALSE );
		}

	return( FALSE );
	}

static int certImport( const int certNo, const BOOLEAN isBase64 )
	{
	CRYPT_CERTIFICATE cryptCert;
	FILE *filePtr;
	BYTE buffer[ BUFFER_SIZE ];
	int count, value, status;

	printf( "Testing %scertificate #%d import...\n",
			isBase64 ? "base64 " : "", certNo );
	filenameFromTemplate( buffer, isBase64 ? BASE64CERT_FILE_TEMPLATE : \
											 CERT_FILE_TEMPLATE, certNo );
	if( ( filePtr = fopen( buffer, "rb" ) ) == NULL )
		{
		puts( "Couldn't find certificate file for import test." );
		return( FALSE );
		}
	count = fread( buffer, 1, BUFFER_SIZE, filePtr );
	fclose( filePtr );

	/* Import the certificate */
	status = cryptImportCert( buffer, count, CRYPT_UNUSED,
							  &cryptCert );
#ifdef __UNIX__
	if( status == CRYPT_ERROR_NOTAVAIL || status == CRYPT_ERROR_BADDATA )
		{
		puts( "The certificate import failed, possibly because you're "
			  "using an\nolder version of unzip that corrupts "
			  "certain types of files when it\nextracts them.  To fix this, "
			  "you need to re-extract test/*.der without\nusing the -a "
			  "option to convert text files.\n" );
		return( TRUE );		/* Skip this test and continue */
		}
#endif /* __UNIX__ */
	if( status == CRYPT_ERROR_NOSECURE && \
		( certNo == 5 || certNo == 12 || certNo == 13 || certNo == 20 || \
		  certNo == 25 ) )
		{
		/* Some older certs use totally insecure 512-bit keys and can't be
		   processed unless we deliberately allow insecure keys.  
		   Unfortunately this also blocks out the cert that's used to check
		   the ability to handle invalid PKCS #1 padding, since this only
		   uses a 512-bit key, but if necessary it can be tested by lowering 
		   MIN_PKCSIZE when building cryptlib */
		puts( "Warning: Certificate import failed because the certificate "
			  "uses a very short\n         (insecure) key." );
		return( TRUE );
		}
	if( cryptStatusError( status ) )
		{
		printf( "cryptImportCert() for cert #%d failed with error code %d, "
				"line %d.\n", certNo, status, __LINE__ );
		return( FALSE );
		}
	status = cryptGetAttribute( cryptCert, CRYPT_CERTINFO_SELFSIGNED,
								&value );
	if( cryptStatusError( status ) )
		{
		/* Sanity check to make sure that the cert internal state is
		   consistent - this should never happen */
		printf( "Couldn't get cert.self-signed status, status %d, line "
				"%d.\n", status, __LINE__ );
		return( FALSE );
		}
	if( value )
		{
		printf( "Certificate is self-signed, checking signature... " );
		status = cryptCheckCert( cryptCert, CRYPT_UNUSED );
		if( cryptStatusError( status ) )
			{
			if( !handleCertError( cryptCert, certNo, status ) )
				return( attrErrorExit( cryptCert, "cryptCheckCert()", 
									   status, __LINE__ ) );
			}
		else
			puts( "signature verified." );
		}
	else
		puts( "Certificate is signed, signature key unknown." );

	/* Print information on what we've got */
	if( !printCertInfo( cryptCert ) )
		return( FALSE );

	/* Clean up */
	cryptDestroyCert( cryptCert );
	puts( "Certificate import succeeded.\n" );
	return( TRUE );
	}

#if 0	/* Test rig for NISCC cert data */

static void importTestData( void )
	{
	int i;

	for( i = 1; i <= 110000; i++ )
		{
		CRYPT_CERTIFICATE cryptCert;
		FILE *filePtr;
		BYTE buffer[ BUFFER_SIZE ];
		int count, status;

		if( !( i % 100 ) )
			printf( "%06d\r", i );
/*		filenameFromTemplate( buffer, "/tmp/simple_client/%08d", i ); */
/*		filenameFromTemplate( buffer, "/tmp/simple_server/%08d", i ); */
		filenameFromTemplate( buffer, "/tmp/simple_rootca/%08d", i );
		if( ( filePtr = fopen( buffer, "rb" ) ) == NULL )
			break;
		count = fread( buffer, 1, BUFFER_SIZE, filePtr );
		fclose( filePtr );
		status = cryptImportCert( buffer, count, CRYPT_UNUSED,
								  &cryptCert );
		if( cryptStatusOK( status ) )
			cryptDestroyCert( cryptCert );
		}
	}
#endif /* 0 */

int testCertImport( void )
	{
	int i;

	for( i = 1; i <= 25; i++ )
		{
		if( !certImport( i, FALSE ) )
			return( FALSE );
		}
	return( TRUE );
	}

static int certReqImport( const int certNo )
	{
	CRYPT_CERTIFICATE cryptCert;
	FILE *filePtr;
	BYTE buffer[ BUFFER_SIZE ];
	int count, complianceValue, status;

	printf( "Testing certificate request #%d import...\n", certNo );
	filenameFromTemplate( buffer, CERTREQ_FILE_TEMPLATE, certNo );
	if( ( filePtr = fopen( buffer, "rb" ) ) == NULL )
		{
		puts( "Couldn't find certificate file for import test." );
		return( FALSE );
		}
	count = fread( buffer, 1, BUFFER_SIZE, filePtr );
	fclose( filePtr );

	/* Import the certificate request and check that the signature is valid */
	if( certNo == 3 )
		{
		/* Some of the requests are broken and we have to set the compliance
		   level to oblivious to handle them */
		cryptGetAttribute( CRYPT_UNUSED, CRYPT_OPTION_CERT_COMPLIANCELEVEL,
						   &complianceValue );
		cryptSetAttribute( CRYPT_UNUSED, CRYPT_OPTION_CERT_COMPLIANCELEVEL,
						   CRYPT_COMPLIANCELEVEL_OBLIVIOUS );
		}
	status = cryptImportCert( buffer, count, CRYPT_UNUSED,
							  &cryptCert );
	if( certNo == 3 )
		cryptSetAttribute( CRYPT_UNUSED, CRYPT_OPTION_CERT_COMPLIANCELEVEL,
						   complianceValue );
#ifdef __UNIX__
	if( status == CRYPT_ERROR_NOTAVAIL || status == CRYPT_ERROR_BADDATA )
		{
		puts( "The certificate request import failed, probably because "
			  "you're using an\nolder version of unzip that corrupts "
			  "certain types of files when it\nextracts them.  To fix this, "
			  "you need to re-extract test/*.der without\nusing the -a "
			  "option to convert text files.\n" );
		return( TRUE );		/* Skip this test and continue */
		}
#endif /* __UNIX__ */
	if( status == CRYPT_ERROR_NOSECURE && certNo == 1 )
		{
		puts( "Warning: Cert.request import failed because the request "
			  "uses a very short\n         (insecure) key." );
		return( TRUE );
		}
	if( cryptStatusError( status ) )
		{
		printf( "cryptImportCert() failed with error code %d, line %d.\n",
				status, __LINE__ );
		return( FALSE );
		}
	printf( "Checking signature... " );
	status = cryptCheckCert( cryptCert, CRYPT_UNUSED );
	if( cryptStatusError( status ) )
		return( attrErrorExit( cryptCert, "cryptCheckCert()", status, 
							   __LINE__ ) );
	puts( "signature verified." );

	/* Print information on what we've got */
	if( !printCertInfo( cryptCert ) )
		return( FALSE );

	/* Clean up */
	cryptDestroyCert( cryptCert );
	puts( "Certificate request import succeeded.\n" );
	return( TRUE );
	}

int testCertReqImport( void )
	{
	int i;

	for( i = 1; i <= 3; i++ )
		if( !certReqImport( i ) )
			return( FALSE );
	return( TRUE );
	}

#define LARGE_CRL_SIZE	32767	/* Large CRL is too big for std.buffer */

static int crlImport( const int crlNo, BYTE *buffer )
	{
	CRYPT_CERTIFICATE cryptCert;
	FILE *filePtr;
	int count, status;

	filenameFromTemplate( buffer, CRL_FILE_TEMPLATE, crlNo );
	if( ( filePtr = fopen( buffer, "rb" ) ) == NULL )
		{
		printf( "Couldn't find CRL file for CRL #%d import test.\n", crlNo );
		return( FALSE );
		}
	count = fread( buffer, 1, LARGE_CRL_SIZE, filePtr );
	fclose( filePtr );
	printf( "CRL #%d has size %d bytes.\n", crlNo, count );

	/* Import the CRL.  Since CRL's don't include the signing cert, we can't
	   (easily) check the signature on it */
	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 and clean up */
	if( !printCertInfo( cryptCert ) )
		return( FALSE );
	cryptDestroyCert( cryptCert );

	return( TRUE );
	}

int testCRLImport( void )
	{
	BYTE *bufPtr;
	int i;

	puts( "Testing CRL import..." );

	/* Since we're working with an unusually large cert object we have to
	   dynamically allocate the buffer for it */
	if( ( bufPtr = malloc( LARGE_CRL_SIZE ) ) == NULL )
		{
		puts( "Out of memory." );
		return( FALSE );
		}
	for( i = 1; i <= 3; i++ )
		if( !crlImport( i, bufPtr ) )
			return( FALSE );

	/* Clean up */
	free( bufPtr );
	puts( "CRL import succeeded.\n" );
	return( TRUE );
	}

static BOOLEAN handleCertChainError( const CRYPT_CERTIFICATE cryptCertChain, 
									 const int certNo, const int errorCode )
	{
	int trustValue = CRYPT_UNUSED, complianceValue = CRYPT_UNUSED;
	int errorLocus, status;

	/* If the chain contains a single non-CA cert, we'll get a parameter 
	   error since we haven't supplied a signing cert */
	if( errorCode == CRYPT_ERROR_PARAM2 )
		{
		cryptSetAttribute( cryptCertChain, CRYPT_CERTINFO_CURRENT_CERTIFICATE,
						   CRYPT_CURSOR_FIRST );
		if( cryptSetAttribute( cryptCertChain,
							   CRYPT_CERTINFO_CURRENT_CERTIFICATE,
							   CRYPT_CURSOR_NEXT ) == CRYPT_ERROR_NOTFOUND )
			{
			/* There's only a single cert present, we can't do much with 
			   it */
			puts( "\nCertificate chain contains only a single standalone "
				  "cert, skipping\nsignature check..." );
			return( TRUE );
			}
		}

	/* If it's not a problem with validity, we can't go any further */
	if( errorCode != CRYPT_ERROR_INVALID )
		return( attrErrorExit( cryptCertChain, "cryptCheckCert()", 
							   errorCode, __LINE__ ) );

	/* Check the nature of the problem */
	status = cryptGetAttribute( cryptCertChain, CRYPT_ATTRIBUTE_ERRORLOCUS,
								&errorLocus );
	if( cryptStatusError( status ) )
		{
		puts( "Couldn't get error locus for certificate check failure." );
		return( FALSE );
		}

	/* Try to work around the error */
	status = errorCode;
	if( errorLocus == CRYPT_CERTINFO_TRUSTED_IMPLICIT || \
		errorLocus == CRYPT_CERTINFO_TRUSTED_USAGE )
		{
		/* The error occured because of a problem with the root cert, try 
		   again with an implicitly-trusted root */
		if( errorLocus == CRYPT_CERTINFO_TRUSTED_IMPLICIT )
			printf( "\nWarning: The certificate chain didn't verify "
					"because it didn't end in a\n         trusted root "
					"certificate.  Checking again using an "
					"implicitly\n         trusted root..." );
		else
			printf( "\nWarning: The certificate chain didn't verify "
					"because the root certificate's\n         key isn't "
					"enabled for this usage.  Checking again using "
					"an\n         implicitly trusted root..." );
		if( cryptStatusError( \
				setRootTrust( cryptCertChain, &trustValue, 1 ) ) )
			{
			printf( "\nAttempt to make chain root implicitly trusted "

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -