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

📄 testkeyd.c

📁 老外写的加密库cryptlib(版本3.1)
💻 C
📖 第 1 页 / 共 2 页
字号:
/****************************************************************************
*																			*
*					cryptlib Database Keyset Test Routines					*
*						Copyright Peter Gutmann 1995-2003					*
*																			*
****************************************************************************/

#ifdef _MSC_VER
  #include "../cryptlib.h"
  #include "../test/test.h"
#else
  #include "cryptlib.h"
  #include "test/test.h"
#endif /* Braindamaged MSC include handling */

#if defined( __MVS__ ) || defined( __VMCMS__ )
  /* Suspend conversion of literals to ASCII. */
  #pragma convlit( suspend )
#endif /* EBCDIC systems */

/****************************************************************************
*																			*
*					Database Keyset Read/Write Tests						*
*																			*
****************************************************************************/

/* Read/write a certificate from a public-key keyset.  Returns 
   CRYPT_ERROR_NOTAVAIL if this keyset type isn't available from this 
   cryptlib build, CRYPT_ERROR_FAILED if the keyset/data source access 
   failed */

static int testKeysetRead( const CRYPT_KEYSET_TYPE keysetType,
						   const char *keysetName,
						   const char *keyName, 
						   const CRYPT_CERTTYPE_TYPE type )
	{
	CRYPT_KEYSET cryptKeyset;
	CRYPT_CERTIFICATE cryptCert;
	int value, status;

	/* Open the keyset with a check to make sure this access method exists 
	   so we can return an appropriate error message */
	status = cryptKeysetOpen( &cryptKeyset, CRYPT_UNUSED, keysetType, 
							  keysetName, CRYPT_KEYOPT_READONLY );
	if( status == CRYPT_ERROR_PARAM3 )
		/* This type of keyset access not available */
		return( CRYPT_ERROR_NOTAVAIL );
	if( cryptStatusError( status ) )
		{
		printf( "cryptKeysetOpen() failed with error code %d, line %d.\n",
				status, __LINE__ );
		return( CRYPT_ERROR_FAILED );
		}

	/* Read the certificate from the keyset */
	status = cryptGetPublicKey( cryptKeyset, &cryptCert, CRYPT_KEYID_NAME,
								keyName );
	if( cryptStatusError( status ) )
		{
		/* The access to network-accessible keysets can be rather 
		   temperamental and can fail at this point even though it's not a
		   fatal error.  The calling code knows this and will continue the
		   self-test with an appropriate warning, so we explicitly clean up 
		   after ourselves to make sure we don't get a CRYPT_ORPHAN on
		   shutdown */
		if( keysetType == CRYPT_KEYSET_HTTP && \
			status == CRYPT_ERROR_NOTFOUND )
			{
			/* 404's are relatively common, and non-fatal */
			extErrorExit( cryptKeyset, "cryptGetPublicKey()", status, __LINE__ );
			puts( "  (404 is a common HTTP error, and non-fatal)." );
			return( TRUE );
			}

		return( extErrorExit( cryptKeyset, "cryptGetPublicKey()", status, 
							  __LINE__ ) );
		}

	/* Make sure we got what we were expecting */
	cryptGetAttribute( cryptCert, CRYPT_CERTINFO_CERTTYPE, &value );
	if( value != type )
		{
		printf( "Expecting certificate object type %d, got %d.", type, value );
		return( FALSE );
		}
	if( value == CRYPT_CERTTYPE_CERTCHAIN || value == CRYPT_CERTTYPE_CRL )
		{
		const BOOLEAN isCertChain = ( value == CRYPT_CERTTYPE_CERTCHAIN ) ? \
									TRUE : FALSE;

		value = 0;
		cryptSetAttribute( cryptCert, CRYPT_CERTINFO_CURRENT_CERTIFICATE, 
						   CRYPT_CURSOR_FIRST );
		do
			value++;
		while( cryptSetAttribute( cryptCert,
								  CRYPT_CERTINFO_CURRENT_CERTIFICATE, 
								  CRYPT_CURSOR_NEXT ) == CRYPT_OK );
		printf( isCertChain ? "Cert chain length = %d.\n" : \
							  "CRL has %d entries.\n", value );
		}

	/* Check the cert against the CRL.  Any kind of error is a failure since
	   the cert isn't in the CRL */
	if( keysetType != CRYPT_KEYSET_LDAP && \
		keysetType != CRYPT_KEYSET_HTTP )
		{
		puts( "Checking certificate against CRL." );
		status = cryptCheckCert( cryptCert, cryptKeyset );
		if( cryptStatusError( status ) )
			return( extErrorExit( cryptKeyset, "cryptCheckCert() (for CRL "
								  "in keyset)", status, __LINE__ ) );
		}

	/* Close the keyset */
	status = cryptKeysetClose( cryptKeyset );
	if( cryptStatusError( status ) )
		{
		printf( "cryptKeysetClose() failed with error code %d, line %d.\n",
				status, __LINE__ );
		return( FALSE );
		}

	cryptDestroyCert( cryptCert );
	return( TRUE );
	}

static int testKeysetWrite( const CRYPT_KEYSET_TYPE keysetType,
							const char *keysetName )
	{
	CRYPT_KEYSET cryptKeyset;
	CRYPT_CERTIFICATE cryptCert;
	BYTE buffer[ BUFFER_SIZE ];
	char name[ CRYPT_MAX_TEXTSIZE + 1 ];
	int length, status;

	/* Import the certificate from a file - this is easier than creating one
	   from scratch.  We use one of the later certs in the text set, since 
	   this contains an email address, which the earlier ones don't */
	status = importCertFromTemplate( &cryptCert, CERT_FILE_TEMPLATE, 5 );
	if( cryptStatusError( status ) )
		{
		puts( "Couldn't read certificate from file, skipping test of keyset "
			  "write..." );
		return( TRUE );
		}

	/* Create the database keyset with a check to make sure this access
	   method exists so we can return an appropriate error message.  If the
	   database table already exists, this will return a duplicate data
	   error so we retry the open with no flags to open the existing database
	   keyset for write access */
	status = cryptKeysetOpen( &cryptKeyset, CRYPT_UNUSED, keysetType, 
							  keysetName, CRYPT_KEYOPT_CREATE );
	if( cryptStatusOK( status ) )
		printf( "Created new certificate database '%s'.\n", keysetName );
	if( status == CRYPT_ERROR_PARAM3 )
		{
		/* This type of keyset access isn't available, return a special error
		   code to indicate that the test wasn't performed, but that this
		   isn't a reason to abort processing */
		cryptDestroyCert( cryptCert );
		return( CRYPT_ERROR_NOTAVAIL );
		}
	if( status == CRYPT_ERROR_DUPLICATE )
		status = cryptKeysetOpen( &cryptKeyset, CRYPT_UNUSED, keysetType, 
								  keysetName, 0 );
	if( cryptStatusError( status ) )
		{
		cryptDestroyCert( cryptCert );
		printf( "cryptKeysetOpen() failed with error code %d, line %d.\n",
				status, __LINE__ );
		if( status == CRYPT_ERROR_OPEN )
			return( CRYPT_ERROR_FAILED );
		return( FALSE );
		}

	/* Write the key to the database */
	puts( "Adding certificate." );
	status = cryptAddPublicKey( cryptKeyset, cryptCert );
	if( status == CRYPT_ERROR_DUPLICATE )
		{
		/* The key is already present, delete it and retry the write */
		status = cryptGetAttributeString( cryptCert, 
								CRYPT_CERTINFO_COMMONNAME, name, &length );
		if( cryptStatusOK( status ) )
			{
			name[ length ] = '\0';
			status = cryptDeleteKey( cryptKeyset, CRYPT_KEYID_NAME, name );
			}
		if( cryptStatusError( status ) )
			return( extErrorExit( cryptKeyset, "cryptDeleteKey()", status, 
								  __LINE__ ) );
		status = cryptAddPublicKey( cryptKeyset, cryptCert );
		}
	if( cryptStatusError( status ) )
		{
		printExtError( cryptKeyset, "cryptAddPublicKey()", status, __LINE__ );

		/* LDAP writes can fail due to the chosen directory not supporting the
		   schema du jour, so we're a bit more careful about cleaning up since
		   we'll skip the error and continue processing */
		cryptDestroyCert( cryptCert );
		cryptKeysetClose( cryptKeyset );
		return( FALSE );
		}
	cryptDestroyCert( cryptCert );

	/* Add a second cert with C=US so that we've got enough certs to properly 
	   exercise the query code.  This cert is highly unusual in that it 
	   doesn't have a DN, so we have to move up the DN looking for higher-up
	   values, in this case the OU */
	if( keysetType != CRYPT_KEYSET_LDAP )
		{
		status = importCertFromTemplate( &cryptCert, CERT_FILE_TEMPLATE, 2 );
		if( cryptStatusError( status ) )
			{
			puts( "Couldn't read second certificate from file, skipping "
				  "remaining keyset write tests..." );
			cryptKeysetClose( cryptKeyset );
			return( TRUE );
			}
		status = cryptAddPublicKey( cryptKeyset, cryptCert );
		if( status == CRYPT_ERROR_DUPLICATE )
			{
			status = cryptGetAttributeString( cryptCert, 
							CRYPT_CERTINFO_COMMONNAME, name, &length );
			if( cryptStatusError( status ) )
				status = cryptGetAttributeString( cryptCert, 
							CRYPT_CERTINFO_ORGANIZATIONALUNITNAME, name, &length );
			if( cryptStatusOK( status ) )
				{
				name[ length ] = '\0';
				status = cryptDeleteKey( cryptKeyset, CRYPT_KEYID_NAME, name );
				}
			if( cryptStatusOK( status ) )
				status = cryptAddPublicKey( cryptKeyset, cryptCert );
			}
		if( cryptStatusError( status ) )
			return( extErrorExit( cryptKeyset, "cryptAddPublicKey()", 
								  status, __LINE__ ) );
		cryptDestroyCert( cryptCert );
		}

	/* Now try the same thing with a CRL.  This code also tests the 
	   duplicate-detection mechanism, if we don't get a duplicate error 
	   there's a problem */
	puts( "Adding CRL." );
	status = importCertFromTemplate( &cryptCert, CRL_FILE_TEMPLATE, 1 );
	if( cryptStatusError( status ) )
		{
		puts( "Couldn't read CRL from file, skipping test of keyset "
			  "write..." );
		return( TRUE );
		}
	status = cryptAddPublicKey( cryptKeyset, cryptCert );
	if( cryptStatusError( status ) && status != CRYPT_ERROR_DUPLICATE )
		return( extErrorExit( cryptKeyset, "cryptAddPublicKey()", status, 
							  __LINE__ ) );
	status = cryptAddPublicKey( cryptKeyset, cryptCert );
	if( status != CRYPT_ERROR_DUPLICATE )
		{
		puts( "Addition of duplicate item to keyset failed to produce "
			  "CRYPT_ERROR_DUPLICATE" );
		return( FALSE );
		}
	cryptDestroyCert( cryptCert );

	/* Finally, try it with a cert chain */
	puts( "Adding cert chain." );
	filenameFromTemplate( buffer, CERTCHAIN_FILE_TEMPLATE, 1 );
	status = importCertFile( &cryptCert, buffer );
	if( cryptStatusError( status ) )
		{
		puts( "Couldn't read cert chain from file." );
		return( FALSE );
		}
	status = cryptAddPublicKey( cryptKeyset, cryptCert );
	if( cryptStatusError( status ) && status != CRYPT_ERROR_DUPLICATE )
		return( extErrorExit( cryptKeyset, "cryptAddPublicKey()", status, 
							  __LINE__ ) );
	cryptDestroyCert( cryptCert );

	/* In addition to the other certs we also add the generic user cert, 
	   which is used later in other tests.  Since it may have been added 
	   earlier, we try and delete it first (we can't use the existing 
	   version since the issuerAndSerialNumber won't match the one in the 
	   private-key keyset) */
	status = getPublicKey( &cryptCert, USER_PRIVKEY_FILE, 
						   USER_PRIVKEY_LABEL );
	if( cryptStatusError( status ) )
		{
		puts( "Couldn't read user cert from file." );
		return( FALSE );
		}
	cryptGetAttributeString( cryptCert, CRYPT_CERTINFO_COMMONNAME,
							 name, &length );
	name[ length ] = '\0';
	do
		status = cryptDeleteKey( cryptKeyset, CRYPT_KEYID_NAME, name );
	while( cryptStatusOK( status ) );
	status = cryptAddPublicKey( cryptKeyset, cryptCert );
	if( status == CRYPT_ERROR_NOTFOUND )
		/* This can occur if a database keyset is defined but hasn't been
		   initialised yet so the necessary tables don't exist, it can be
		   opened but an attempt to add a key will return a not found error 
		   since it's the table itself rather than any item within it that 
		   isn't being found */
		status = CRYPT_OK;
	if( cryptStatusError( status ) )
		return( extErrorExit( cryptKeyset, "cryptAddPublicKey()", status, 
							  __LINE__ ) );
	cryptDestroyCert( cryptCert );

	/* Make sure the deletion code works properly.  This is an artifact of
	   the way RDBMS' work, the delete query can execute successfully but
	   not delete anything so we make sure the glue code correctly 
	   translates this into a CRYPT_DATA_NOTFOUND */
	status = cryptDeleteKey( cryptKeyset, CRYPT_KEYID_NAME,
							 "Mr.Not Appearing in this Keyset" );
	if( status != CRYPT_ERROR_NOTFOUND )
		{
		puts( "Attempt to delete a nonexistant key reports success, the "
			  "database backend glue\ncode needs to be fixed to handle this "
			  "correctly." );
		return( FALSE );
		}

	/* Close the keyset */
	status = cryptKeysetClose( cryptKeyset );
	if( cryptStatusError( status ) )
		printf( "cryptKeysetClose() failed with error code %d, line %d.\n",
				status, __LINE__ );

	return( TRUE );
	}

/* Perform a general keyset query */

int testQuery( const CRYPT_KEYSET_TYPE keysetType, const char *keysetName )
	{
	CRYPT_KEYSET cryptKeyset;
	int count = 0, status;

	/* Open the database keyset */
	status = cryptKeysetOpen( &cryptKeyset, CRYPT_UNUSED, keysetType, 
							  keysetName, CRYPT_KEYOPT_READONLY );
	if( cryptStatusError( status ) )
		{
		printf( "cryptKeysetOpen() failed with error code %d, line %d.\n",
				status, __LINE__ );
		if( status == CRYPT_ERROR_OPEN )
			return( CRYPT_ERROR_FAILED );
		return( FALSE );
		}

	/* Send the query to the database and read back the results */
	status = cryptSetAttributeString( cryptKeyset, CRYPT_KEYINFO_QUERY, 
									  "$C='US'", 7 );
	if( cryptStatusError( status ) )
		return( extErrorExit( cryptKeyset, "Keyset query", status, 
							  __LINE__ ) );
	do
		{
		CRYPT_CERTIFICATE cryptCert;

		status = cryptGetPublicKey( cryptKeyset, &cryptCert,
									CRYPT_KEYID_NONE, NULL );
		if( cryptStatusOK( status ) )
			{
			count++;
			cryptDestroyCert( cryptCert );
			}
		}
	while( cryptStatusOK( status ) );
	if( cryptStatusError( status ) && status != CRYPT_ERROR_COMPLETE )
		return( extErrorExit( cryptKeyset, "cryptGetPublicKey()", status, 
							  __LINE__ ) );
	if( count < 2 )
		{
		puts( "Only one certificate was returned, this indicates that the "
			  "database backend\nglue code isn't processing ongoing queries "
			  "correctly." );
		return( FALSE );
		}
	printf( "%d certificate(s) matched the query.\n", count );

	/* Close the keyset */
	status = cryptKeysetClose( cryptKeyset );
	if( cryptStatusError( status ) )
		{
		printf( "cryptKeysetClose() failed with error code %d, line %d.\n",
				status, __LINE__ );
		return( FALSE );
		}

	return( TRUE );
	}

/* Read/write/query a certificate from a database keyset */

int testReadCert( void )
	{
	CRYPT_CERTIFICATE cryptCert;
	char name[ CRYPT_MAX_TEXTSIZE + 1 ];
	int length, status;

⌨️ 快捷键说明

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