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

📄 certimp.c

📁 cryptlib安全工具包
💻 C
📖 第 1 页 / 共 3 页
字号:
		/* Checking in normal mode should fail */
		printf( "cryptCheckCert() of broken cert succeeded when it should "
				"have failed, line %d.\n", __LINE__ );
		return( FALSE );
		}
	cryptSetAttribute( CRYPT_UNUSED, CRYPT_OPTION_CERT_COMPLIANCELEVEL,
					   CRYPT_COMPLIANCELEVEL_OBLIVIOUS );
	status = cryptCheckCert( cryptCert, cryptCaCert );
	cryptSetAttribute( CRYPT_UNUSED, CRYPT_OPTION_CERT_COMPLIANCELEVEL,
					   value );
	if( cryptStatusError( status ) )
		{
		/* Checking in oblivious mode should succeed */
		printf( "cryptCheckCert() of broken cert failed when it should "
				"have succeeded, line %d.\n", __LINE__ );
		return( FALSE );
		}
	cryptDestroyCert( cryptCaCert );
	cryptDestroyCert( cryptCert );

	/* Clean up */
	puts( "Certificate handling at different compliance levels succeeded.\n" );
	return( TRUE );
	}

/* Test path processing using the NIST PKI test suite.  This doesn't run all
   of the tests since some are somewhat redundant (e.g. path length 
   constraints ending at cert n in a chain vs.cert n+1 in a chain where
   both are well short of the constraint length) or require complex
   additional processing (e.g. CRL fetches) which it's difficult to
   automate */

typedef struct {
	const int fileMajor, fileMinor;	/* Major and minor number of file */
	const BOOLEAN isValid;			/* Whether path is valid */
	const BOOLEAN policyOptional;	/* Whether explicit policy optional */
	} PATH_TEST_INFO;

static const PATH_TEST_INFO FAR_BSS pathTestInfo[] = {
	/* Signature verification */
	/*  0 */ { 1, 1, TRUE },
	/*  1 */ { 1, 2, FALSE },
	/*  2 */ { 1, 3, FALSE },
	/*  3 */ { 1, 4, TRUE },
	/*  4 */ { 1, 6, FALSE },

	/* Validity periods */
	/*  5 */ { 2, 1, FALSE },
	/*  6 */ { 2, 2, FALSE },
	/* The second cert in test 4.2.3 has a validFrom date of 1950 which
	   cryptlib rejects on import as being not even remotely valid (it can't
	   even be represented in the ANSI/ISO C date format).  Supposedly half-
	   century-old certs are symptomatic of severely broken software so
	   rejecting this cert is justified */
/*	{ 2, 3, TRUE }, */
	/*  7 */ { 2, 4, TRUE },
	/*  8 */ { 2, 5, FALSE },
	/*  9 */ { 2, 6, FALSE },
	/* 10 */ { 2, 7, FALSE },
	/* 11 */ { 2, 8, TRUE },

	/* Name chaining */
	/* 12 */ { 3, 1, FALSE },
	/* 13 */ { 3, 6, TRUE },
	/* 14 */ { 3, 8, TRUE },
	/* 15 */ { 3, 9, TRUE },

	/* 4 = CRLs */

	/* oldWithNew / newWithOld */
	/* 16 */ { 5, 1, TRUE },
	/* 17 */ { 5, 3, TRUE },

	/* Basic constraints */
	/* 18 */ { 6, 1, FALSE },
	/* 19 */ { 6, 2, FALSE },
	/* 20 */ { 6, 5, FALSE },
	/* 21 */ { 6, 6, FALSE },
	/* 22 */ { 6, 7, TRUE },
	/* The second-to-last cert in the path sets a pathLenConstraint of zero
	   with the next cert being a CA cert (there's no EE cert present).
	   cryptlib treats this as invalid since it can never lead to a valid
	   path once the EE cert is added */
	/* 23 */ { 6, 8, FALSE /* TRUE */ },
	/* 24 */ { 6, 9, FALSE },
	/* 25 */ { 6, 11, FALSE },
	/* 26 */ { 6, 12, FALSE },
	/* 27 */ { 6, 13, TRUE },
	/* As for 4.6.8 */
	/* 28 */ { 6, 14, FALSE /* TRUE */ },
	/* The following are 4.5.x-style oldWithNew / newWithOld but with path
	   constraints */
	/* 29 */ { 6, 15, TRUE },
	/* 30 */ { 6, 16, FALSE },
	/* 31 */ { 6, 17, TRUE },

	/* Key usage */
	/* 32 */ { 7, 1, FALSE },
	/* 33 */ { 7, 2, FALSE },

	/* Policies */
	/* The first cert asserts a policy that differs from that of all other
	   certs in the path.  If no explicit policy is required (by setting
	   CRYPT_OPTION_REQUIREPOLICY to FALSE) it will verify, otherwise it
	   won't */
	/* 34 */ { 8, 3, TRUE, TRUE },	/* Policy optional */
	/* 35 */ { 8, 3, FALSE },
	/* 36 */ { 8, 4, FALSE },
	/* 37 */ { 8, 6, TRUE },
	/* 38 */ { 8, 10, TRUE },
	/* 39 */ { 8, 11, TRUE },
	/* 40 */ { 8, 14, TRUE },
	/* 41 */ { 8, 15, TRUE },
	/* 42 */ { 8, 20, TRUE },

	/* Policy constraints.  For these tests policy handling is dictated by
	   policy constraints so we don't require explicit policies */
	/* 43 */ { 9, 2, TRUE, TRUE },
	/* The NIST test value for this one is wrong.  RFC 3280 section 4.2.1.12
	   says:

		If the requireExplicitPolicy field is present, the value of
		requireExplicitPolicy indicates the number of additional
		certificates that may appear in the path before an explicit policy
		is required for the entire path.  When an explicit policy is
		required, it is necessary for all certificates in the path to
		contain an acceptable policy identifier in the certificate policies
		extension.

	   Test 4.9.3 has requireExplicitPolicy = 4 in a chain of 4 certs for
	   which the last one has no policy.  NIST claims this shouldn't
	   validate, which is incorrect */
	/* 44 */ { 9, 3, TRUE /* FALSE */, TRUE },
	/* 45 */ { 9, 4, TRUE, TRUE },
	/* 46 */ { 9, 5, FALSE, TRUE },
	/* 47 */ { 9, 6, TRUE, TRUE },
	/* 48 */ { 9, 7, FALSE, TRUE },

	/* 10, 11 = Policy mappings */
	/* 49 */ { 10, 7, FALSE },
	/* 50 */ { 10, 8, FALSE },

	/* Policy inhibitAny */
	/* 51 */ { 12, 1, FALSE },
	/* 52 */ { 12, 2, TRUE },
	/* 53 */ { 12, 3, TRUE },
	/* 54 */ { 12, 4, FALSE },
	/* The NIST test results for 4.12.7 and 4.12.9 are wrong or more
	   specifically the PKIX spec is wrong, contradicting itself in the body
	   of the spec and the path-processing pseudocode in that there's no
	   path-kludge exception for policy constraints in the body but there is 
	   one in the pseudocode.  Since these chains contain path-kludge certs 
	   the paths are invalid - they would only be valid if there was a path-
	   kludge exception for inhibitAnyPolicy.  Note that 4.9.7 and 4.9.8 
	   have the same conditions for requireExplicitPolicy but this time the 
	   NIST test results go the other way.  So although the PKIX spec is 
	   wrong the NIST test is also wrong in that it applies an inconsistent 
	   interpretation of the contradictions in the PKIX spec */
	/* 55 */ { 12, 7, FALSE /* TRUE */ },
	/* 56 */ { 12, 8, FALSE },
	/* 57 */ { 12, 9, FALSE /* TRUE */ },

	/* Name constraints */
	/* 58 */ { 13, 1, TRUE },
	/* 59 */ { 13, 2, FALSE },
	/* 60 */ { 13, 3, FALSE },
	/* 61 */ { 13, 4, TRUE },
	/* 62 */ { 13, 5, TRUE },
	/* 63 */ { 13, 6, TRUE },
	/* 64 */ { 13, 7, FALSE },
	/* 65 */ { 13, 8, FALSE },
	/* 66 */ { 13, 9, FALSE },
	/* 67 */ { 13, 10, FALSE },
	/* 68 */ { 13, 11, TRUE },
	/* 69 */ { 13, 12, FALSE },
	/* 70 */ { 13, 13, FALSE },
	/* 71 */ { 13, 14, TRUE },
	/* 72 */ { 13, 15, FALSE },
	/* 73 */ { 13, 17, FALSE },
	/* 74 */ { 13, 18, TRUE },
	/* 75 */ { 13, 19, TRUE },
	/* 76 */ { 13, 20, FALSE },
	/* 77 */ { 13, 21, TRUE },
	/* 78 */ { 13, 22, FALSE },
	/* 79 */ { 13, 23, TRUE },
	/* 80 */ { 13, 24, FALSE },
	/* 81 */ { 13, 25, TRUE },
	/* 82 */ { 13, 26, FALSE },
	/* 83 */ { 13, 27, TRUE },
	/* 84 */ { 13, 28, FALSE },
	/* 85 */ { 13, 29, FALSE },
	/* 86 */ { 13, 30, TRUE },
	/* 87 */ { 13, 31, FALSE },
	/* 88 */ { 13, 32, TRUE },
	/* 89 */ { 13, 33, FALSE },
	/* 90 */ { 13, 34, TRUE },
	/* 91 */ { 13, 35, FALSE },
	/* 92 */ { 13, 36, TRUE },
	/* 93 */ { 13, 37, FALSE },
	/* The NIST test results for 4.13.38 are wrong.  PKIX section 4.2.1.11
	   says:

		DNS name restrictions are expressed as foo.bar.com.  Any DNS name
		that can be constructed by simply adding to the left hand side of
		the name satisfies the name constraint.  For example,
		www.foo.bar.com would satisfy the constraint but foo1.bar.com would
		not.

	   The permitted subtree is testcertificates.gov and the altName is
	   mytestcertificates.gov which satisfies the above rule so the path
	   should be valid and not invalid */
	/* 94 */ { 13, 38, TRUE /* FALSE */ },

	/* 14, 15 = CRLs */

	/* Private cert extensions */
	/* 95 */ { 16, 1, TRUE },
	/* 96 */ { 16, 2, FALSE },
	{ 0, 0 }
	};

static int testPath( const PATH_TEST_INFO *pathInfo )
	{
	CRYPT_CERTIFICATE cryptCertPath;
	char pathName[ 64 ];
	int pathNo, requirePolicy, status;

	/* Convert the composite path info into a single number used for fetching
	   the corresponding data file */
	sprintf( pathName, "4%d%d", pathInfo->fileMajor, pathInfo->fileMinor );
	pathNo = atoi( pathName );

	/* Test the path */
	sprintf( pathName, "4.%d.%d", pathInfo->fileMajor, pathInfo->fileMinor );
	printf( "  Path %s%s...", pathName, pathInfo->policyOptional ? \
			" without explicit policy" : "" );
	status = importCertFromTemplate( &cryptCertPath,
									 PATHTEST_FILE_TEMPLATE, pathNo );
	if( cryptStatusError( status ) )
		{
		printf( "Cert import for test path %s failed, line %d.\n",
				pathName, __LINE__ );
		return( FALSE );
		}
	if( pathInfo->policyOptional )
		{
		/* By default we require policy chaining, for some tests we can turn
		   this off to check non-explict policy processing */
		cryptGetAttribute( CRYPT_UNUSED, CRYPT_OPTION_CERT_REQUIREPOLICY,
						   &requirePolicy );
		assert( requirePolicy != FALSE );
		cryptSetAttribute( CRYPT_UNUSED, CRYPT_OPTION_CERT_REQUIREPOLICY,
						   FALSE );
		}
	status = cryptCheckCert( cryptCertPath, CRYPT_UNUSED );
	if( pathInfo->policyOptional )
		cryptSetAttribute( CRYPT_UNUSED, CRYPT_OPTION_CERT_REQUIREPOLICY,
						   requirePolicy );
	if( pathInfo->isValid )
		{
		if( cryptStatusError( status ) )
			{
			puts( " didn't verify even though it should be valid." );
			return( attrErrorExit( cryptCertPath, "cryptCheckCert()",
								   status, __LINE__ ) );
			}
		}
	else
		if( cryptStatusOK( status ) )
			{
			puts( " verified even though it should have failed." );
			return( FALSE );
			}
	puts( " succeeded." );
	cryptDestroyCert( cryptCertPath );

	return( TRUE );
	}

int testPathProcessing( void )
	{
	CRYPT_CERTIFICATE cryptRootCert;
	int certTrust, complianceLevel, i, status;

	puts( "Testing path processing..." );

	/* Get the root cert and make it implicitly trusted and crank the
	   compliance level up to maximum, since we're going to be testing some
	   pretty obscure extensions */
	status = importCertFromTemplate( &cryptRootCert,
									 PATHTEST_FILE_TEMPLATE, 0 );
	if( cryptStatusOK( status ) )
		status = setRootTrust( cryptRootCert, &certTrust, 1 );
	if( cryptStatusError( status ) )
		{
		printf( "Couldn't create trusted root cert for path processing, "
				"line %d.\n", __LINE__ );
		return( FALSE );
		}
	cryptGetAttribute( CRYPT_UNUSED, CRYPT_OPTION_CERT_COMPLIANCELEVEL,
					   &complianceLevel );
	cryptSetAttribute( CRYPT_UNUSED, CRYPT_OPTION_CERT_COMPLIANCELEVEL,
					   CRYPT_COMPLIANCELEVEL_PKIX_FULL );

	/* Process each cert path and make sure that it succeeds or fails as
	   required */
	for( i = 0; pathTestInfo[ i ].fileMajor; i++ )
		{
		if( !testPath( &pathTestInfo[ i ] ) )
			break;
		}
	setRootTrust( cryptRootCert, NULL, certTrust );
	cryptDestroyCert( cryptRootCert );
	cryptSetAttribute( CRYPT_UNUSED, CRYPT_OPTION_CERT_COMPLIANCELEVEL,
					   complianceLevel );
	if( pathTestInfo[ i ].fileMajor )
		return( FALSE );

	puts( "Path processing succeeded." );
	return( TRUE );
	}

/* Test handling of invalid PKCS #1 padding in cert signatures.  Note that
   running this test properly requires disabling the PKCS#1 padding format 
   check in decodePKCS1() in mechs/mech_sig.c since the signatures have such 
   an obviously dodgy format that they don't even make it past the basic 
   padding sanity check */

int testPKCS1Padding( void )
	{
	CRYPT_CERTIFICATE cryptCert;
	int i, complianceValue, status;

	puts( "Testing invalid PKCS #1 padding handling..." );

	/* The test certs don't have a keyUsage present in a CA cert so we have 
	   to lower the compliance level to be able to get past this check tot he
	   signatures */
	cryptGetAttribute( CRYPT_UNUSED, CRYPT_OPTION_CERT_COMPLIANCELEVEL,
					   &complianceValue );
	cryptSetAttribute( CRYPT_UNUSED, CRYPT_OPTION_CERT_COMPLIANCELEVEL,
					   CRYPT_COMPLIANCELEVEL_OBLIVIOUS );
	for( i = 1; i <= 11; i++ )
		{
		status = importCertFromTemplate( &cryptCert, PADTEST_FILE_TEMPLATE,
										 i );
		if( cryptStatusError( status ) )
			{
			printf( "Couldn't import cert for PKCS #1 padding check, status "
					"%d, line %d.\n", status, __LINE__ );
			return( FALSE );
			}
		status = cryptCheckCert( cryptCert, CRYPT_UNUSED );
		if( cryptStatusOK( status ) )
			{
			printf( "Cert with bad PKSC #1 padding verified, should have "
					"failed, line %d.\n", __LINE__ );
			return( FALSE );
			}
		cryptDestroyCert( cryptCert );
		}
	cryptSetAttribute( CRYPT_UNUSED, CRYPT_OPTION_CERT_COMPLIANCELEVEL,
					   complianceValue );

	puts( "Padding handling succeeded (all certs rejected).\n" );
	return( TRUE );
	}

/* Generic test routines used for debugging.  These are only meant to be
   used interactively, and throw exceptions rather than returning status
   values */

void xxxCertImport( const char *fileName )
	{
	CRYPT_CERTIFICATE cryptCert;
	FILE *filePtr;
	BYTE buffer[ BUFFER_SIZE ], *bufPtr = buffer;
	long length, count;
	int status;

	filePtr = fopen( fileName, "rb" );
	assert( filePtr != NULL );
	fseek( filePtr, 0L, SEEK_END );
	length = ftell( filePtr );
	fseek( filePtr, 0L, SEEK_SET );
	if( length > BUFFER_SIZE )
		{
		bufPtr = malloc( length );
		assert( bufPtr != NULL );
		}
	count = fread( bufPtr, 1, length, filePtr );
	assert( count == length );
	fclose( filePtr );
	status = cryptImportCert( bufPtr, count, CRYPT_UNUSED, &cryptCert );
	assert( cryptStatusOK( status ) );
	if( bufPtr != buffer )
		free( bufPtr );
	printCertInfo( cryptCert );
	cryptDestroyCert( cryptCert );
	}

void xxxCertCheck( const C_STR certFileName, const C_STR caFileNameOpt )
	{
	CRYPT_CERTIFICATE cryptCert, cryptCaCert;
	int status;

	status = importCertFile( &cryptCert, certFileName );
	assert( cryptStatusOK( status ) );
	if( caFileNameOpt == NULL )
		cryptCaCert = CRYPT_UNUSED;
	else
		{
		status = importCertFile( &cryptCaCert, caFileNameOpt );
		assert( cryptStatusOK( status ) );
		}
	status = cryptCheckCert( cryptCert, cryptCaCert );
	if( cryptStatusError( status ) )
		printErrorAttributeInfo( cryptCert );
	assert( cryptStatusOK( status ) );
	cryptDestroyCert( cryptCert );
	cryptDestroyCert( cryptCaCert );
	}

⌨️ 快捷键说明

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