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

📄 dbx_misc.c

📁 cryptlib安全工具包
💻 C
📖 第 1 页 / 共 3 页
字号:
	}

/* Get a certID for a certificate */

CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \
int getCertKeyID( OUT_BUFFER( keyIdMaxLen, *keyIdLen ) char *keyID, 
				  IN_LENGTH_SHORT_MIN( 16 ) const int keyIdMaxLen, 
				  OUT_LENGTH_SHORT_Z int *keyIdLen,
				  IN_HANDLE const CRYPT_CERTIFICATE iCryptCert )
	{
	int status;

	assert( isWritePtr( keyID, keyIdMaxLen ) );
	assert( isWritePtr( keyIdLen, sizeof( int ) ) );

	REQUIRES( keyIdMaxLen >= 16 && keyIdMaxLen < MAX_INTLENGTH_SHORT );
	REQUIRES( isHandleRangeValid( iCryptCert ) );

	/* Clear return values */
	memset( keyID, 0, min( 16, keyIdMaxLen ) );
	*keyIdLen = 0;

	/* Certificate keyID handling isn't quite as simple as just reading an
	   attribute from the certificate since the subjectKeyIdentifier (if
	   present) may not be the same as the keyID if the certificate has come 
	   from a CA that does strange things with the sKID.  To resolve this we 
	   try and build the key ID from the sKID, if this isn't present we use 
	   the keyID (the sKID may have a nonstandard length since it's possible 
	   to stuff anything in there, getKeyID() will hash it to the standard 
	   size if the length is wrong) */
	status = getKeyID( keyID, keyIdMaxLen, keyIdLen, iCryptCert,
					   CRYPT_CERTINFO_SUBJECTKEYIDENTIFIER );
	if( cryptStatusOK( status ) )
		return( status );

	/* There's no subjectKeyIdentifier, use the keyID.  Note that we can't
	   just read the CRYPT_IATTRIBUTE_KEYID attribute directly since this
	   may be a data-only certificate (either a standalone certificate or 
	   one from the middle of a chain) so we have to generate it indirectly 
	   by hashing the SubjectPublicKeyInfo, which is equivalent to the keyID 
	   and is always present in a certificate */
	return( getKeyID( keyID, keyIdMaxLen, keyIdLen, iCryptCert, 
					  CRYPT_IATTRIBUTE_SPKI ) );
	}

/* Extract certificate data from a certificate object.  Note that the 
   formatType is given as an int rather than an enumerated type because
   it can be either a CRYPT_CERTFORMAT_TYPE or a CRYPT_ATTRIBUTE_TYPE */

CHECK_RETVAL STDC_NONNULL_ARG( ( 3, 5 ) ) \
int extractCertData( IN_HANDLE const CRYPT_CERTIFICATE iCryptCert, 
					 IN_INT const int formatType,
					 OUT_BUFFER( certDataMaxLength, *certDataLength ) \
						void *certDataBuffer, 
					 IN_LENGTH_SHORT_MIN( MIN_CRYPT_OBJECTSIZE ) \
						const int certDataMaxLength, 
					 OUT_LENGTH_SHORT_Z int *certDataLength )
	{
	MESSAGE_DATA msgData;
	int status;

	assert( isWritePtr( certDataBuffer, certDataMaxLength ) );
	assert( isWritePtr( certDataLength, sizeof( int ) ) );

	REQUIRES( isHandleRangeValid( iCryptCert ) );
	REQUIRES( formatType == CRYPT_CERTFORMAT_CERTIFICATE || \
			  formatType == CRYPT_ICERTFORMAT_DATA || \
			  formatType == CRYPT_IATTRIBUTE_CRLENTRY );
	REQUIRES( certDataMaxLength >= MIN_CRYPT_OBJECTSIZE && \
			  certDataMaxLength < MAX_INTLENGTH_SHORT );

	/* Make sure that there's no collision in format type values (although 
	   the switch() statement will also catch this by producing a compile 
	   error */
	assert( CRYPT_CERTFORMAT_CERTIFICATE != CRYPT_ICERTFORMAT_DATA && \
			CRYPT_CERTFORMAT_CERTIFICATE != CRYPT_IATTRIBUTE_CRLENTRY );

	/* Clear return values */
	memset( certDataBuffer, 0, min( 16, certDataMaxLength ) );
	*certDataLength = 0;

	/* Extract the certificate object data */
	setMessageData( &msgData, certDataBuffer, certDataMaxLength );
	switch( formatType )
		{
		case CRYPT_CERTFORMAT_CERTIFICATE:
		case CRYPT_ICERTFORMAT_DATA:
			status = krnlSendMessage( iCryptCert, IMESSAGE_CRT_EXPORT,
									  &msgData, formatType );
			break;

		case CRYPT_IATTRIBUTE_CRLENTRY:
			status = krnlSendMessage( iCryptCert, IMESSAGE_GETATTRIBUTE_S, 
									  &msgData, formatType );
			break;

		default:
			retIntError();
		}
	if( cryptStatusError( status ) )
		return( status );
	*certDataLength = msgData.length;

	return( CRYPT_OK );
	}

/* Some internal actions set extended error codes as a result of their 
   operation that the user shouldn't really see.  For example performing a 
   certificate cleanup will return a no-data-found error once the last 
   certificate is reached, which will be read by the user the next time that 
   they read the CRYPT_ATTRIBUTE_INT_ERRORCODE/CRYPT_ATTRIBUTE_INT_ERRORMESSAGE 
   even though the error came from a previous internal operation.  To avoid
   this problem we clean up the error status information when it's been set 
   by an internal operation */

RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
int resetErrorInfo( INOUT DBMS_INFO *dbmsInfo )
	{
	DBMS_STATE_INFO *dbmsStateInfo = dbmsInfo->stateInfo;
	ERROR_INFO *errorInfo = &dbmsStateInfo->errorInfo;

	assert( isWritePtr( dbmsInfo, sizeof( DBMS_INFO ) ) );

	memset( errorInfo, 0, sizeof( ERROR_INFO ) );
	return( CRYPT_OK );
	}

/* Get names for various items */

CHECK_RETVAL_PTR \
char *getKeyName( IN_KEYID const CRYPT_KEYID_TYPE keyIDtype )
	{
	REQUIRES_N( keyIDtype > CRYPT_KEYID_NONE && \
				keyIDtype <= CRYPT_KEYID_LAST );
				/* CRYPT_KEYID_LAST is mapped to the database-use-only 
				   lookup value "nameID" */

	switch( keyIDtype )
		{
		case CRYPT_KEYID_NAME:
			return( "CN" );

		case CRYPT_KEYID_URI:
			return( "email" );

		case CRYPT_IKEYID_KEYID:
			return( "keyID" );

		case CRYPT_IKEYID_ISSUERID:
			return( "issuerID" );

		case CRYPT_IKEYID_CERTID:
			return( "certID" );

		case CRYPT_KEYID_LAST:
			return( "nameID" );
		}

	retIntError_Null();
	}

/****************************************************************************
*																			*
*							Database Access Functions						*
*																			*
****************************************************************************/

/* Create a new key database */

CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \
static int createDatabase( INOUT DBMS_INFO *dbmsInfo, 
						   const BOOLEAN hasPermissions, 
						   INOUT ERROR_INFO *errorInfo )
	{
	int updateProgress = 0, status;

	assert( isWritePtr( dbmsInfo, sizeof( DBMS_INFO ) ) );

	REQUIRES( errorInfo != NULL );

	/* Create tables for certificates, CRLs, certificate requests, PKI 
	   users, and CA logs.  We use CHAR rather than VARCHAR for the ID 
	   fields since these always have a fixed length and CHAR is faster than 
	   VARCHAR.  In addition we make as many columns as possible NOT NULL 
	   since these fields should always be present and because this is  
	   faster for most databases.  The BLOB type is nonstandard, this is 
	   rewritten by the database interface layer to the type which is 
	   appropriate for the database */
	status = dbmsStaticUpdate(
			"CREATE TABLE certificates ("
				"C CHAR(2), "
				"SP VARCHAR(64), "
				"L VARCHAR(64), "
				"O VARCHAR(64), "
				"OU VARCHAR(64), "
				"CN VARCHAR(64), "
				"email VARCHAR(64), "
				"validTo DATETIME NOT NULL, "
				"nameID CHAR(" TEXT_DBXKEYID_SIZE ") NOT NULL, "
				"issuerID CHAR(" TEXT_DBXKEYID_SIZE ") NOT NULL, "
				"keyID CHAR(" TEXT_DBXKEYID_SIZE ") NOT NULL, "
				"certID CHAR(" TEXT_DBXKEYID_SIZE ") NOT NULL, "
				"certData BLOB NOT NULL)" );
	if( cryptStatusError( status ) )
		{
		retExtErr( status, 
				   ( status, errorInfo, getDbmsErrorInfo( dbmsInfo ),
					 "Couldn't create certificate database: " ) );
		}
	if( isCertStore( dbmsInfo ) )
		{
		/* The certificate store contains in addition to the other CRL 
		   fields the certificate expiry time which is used to remove the 
		   entry from the CRL table once the certificate has expired anyway, 
		   the nameID which is used to force clustering of entries for each 
		   CA, and the ID of the certificate being revoked, which isn't 
		   available if we're creating it from a raw CRL */
		status = dbmsStaticUpdate(
			"CREATE TABLE CRLs ("
				"expiryDate DATETIME NOT NULL, "
				"nameID CHAR(" TEXT_DBXKEYID_SIZE ") NOT NULL, "
				"issuerID CHAR(" TEXT_DBXKEYID_SIZE ") NOT NULL,"
				"certID CHAR(" TEXT_DBXKEYID_SIZE ") NOT NULL, "
				"certData BLOB NOT NULL)" );
		if( cryptStatusOK( status ) )
			{
			updateProgress++;
			status = dbmsStaticUpdate(
			"CREATE TABLE pkiUsers ("
				"C CHAR(2), "
				"SP VARCHAR(64), "
				"L VARCHAR(64), "
				"O VARCHAR(64), "
				"OU VARCHAR(64), "
				"CN VARCHAR(64), "
				"nameID CHAR(" TEXT_DBXKEYID_SIZE ") NOT NULL, "
				"keyID CHAR(" TEXT_DBXKEYID_SIZE ") NOT NULL, "
				"certID CHAR(" TEXT_DBXKEYID_SIZE ") NOT NULL, "
				"certData BLOB NOT NULL)" );
			}
		if( cryptStatusOK( status ) )
			{
			updateProgress++;
			status = dbmsStaticUpdate(
			"CREATE TABLE certRequests ("
				"type SMALLINT NOT NULL, "
				"C CHAR(2), "
				"SP VARCHAR(64), "
				"L VARCHAR(64), "
				"O VARCHAR(64), "
				"OU VARCHAR(64), "
				"CN VARCHAR(64), "
				"email VARCHAR(64), "
				"certID CHAR(" TEXT_DBXKEYID_SIZE ") NOT NULL, "
				"certData BLOB NOT NULL)" );
			}
		if( cryptStatusOK( status ) )
			{
			updateProgress++;
			status = dbmsStaticUpdate(
			"CREATE TABLE certLog ("
				"action SMALLINT NOT NULL, "
				"actionTime DATETIME NOT NULL, "
				"certID CHAR(" TEXT_DBXKEYID_SIZE ") NOT NULL, "
				"reqCertID CHAR(" TEXT_DBXKEYID_SIZE "), "
				"subjCertID CHAR(" TEXT_DBXKEYID_SIZE "), "
				"certData BLOB)" );
			}
		}
	else
		{
		status = dbmsStaticUpdate(
			"CREATE TABLE CRLs ("
				"issuerID CHAR(" TEXT_DBXKEYID_SIZE ") NOT NULL,"
				"certData BLOB NOT NULL)" );
		}
	if( cryptStatusError( status ) )
		{
		/* Undo the previous table creations */
		dbmsStaticUpdate( "DROP TABLE certificates" );
		if( updateProgress > 0 )
			dbmsStaticUpdate( "DROP TABLE CRLs" );
		if( updateProgress > 1 )
			dbmsStaticUpdate( "DROP TABLE pkiUsers" );
		if( updateProgress > 2 )
			dbmsStaticUpdate( "DROP TABLE certRequests" );
		retExtErr( status, 
				   ( status, errorInfo, getDbmsErrorInfo( dbmsInfo ),
					 "Couldn't create certificate%s database: ",
					 isCertStore( dbmsInfo ) ? " store" : "" ) );
		}

	/* Create an index for the email address, nameID, issuerID, keyID, and
	   certID in the certificates table, the issuerID and certID in the CRLs
	   table (the CRL nameID isn't indexed since we only use it for linear
	   scans), the nameID and keyID in the PKI users table (the former isn't 
	   used but is made a UNIQUE INDEX to ensure that the same entry can't 
	   be added more than once) and the certID in the certificate log (this 
	   also isn't used but is made a UNIQUE INDEX to ensure that the same 
	   entry can't be added more than once).  We have to give these unique 
	   names since some databases don't allow two indexes to have the same 
	   name even if they're in a different table.  Since most of the fields 
	   in the tables are supposed to be unique we can specify this for the 
	   indexes that we're creating, however we can't do it for the email 
	   address or the nameID in the certificates table since there could be 
	   multiple certificates present that differ only in key usage.  We 
	   don't index the other tables since indexes consume space and we don't 
	   expect to access any of these much */
	status = dbmsStaticUpdate(
			"CREATE INDEX emailIdx ON certificates(email)" );
	if( cryptStatusOK( status ) )
		status = dbmsStaticUpdate(
			"CREATE INDEX nameIDIdx ON certificates(nameID)" );
	if( cryptStatusOK( status ) )
		status = dbmsStaticUpdate(
			"CREATE UNIQUE INDEX issuerIDIdx ON certificates(issuerID)" );
	if( cryptStatusOK( status ) )
		status = dbmsStaticUpdate(
			"CREATE UNIQUE INDEX keyIDIdx ON certificates(keyID)" );
	if( cryptStatusOK( status ) )
		status = dbmsStaticUpdate(
			"CREATE UNIQUE INDEX certIDIdx ON certificates(certID)" );
	if( cryptStatusOK( status ) )
		status = dbmsStaticUpdate(
			"CREATE UNIQUE INDEX crlIssuerIDIdx ON CRLs (issuerID)" );
	if( cryptStatusOK( status ) && isCertStore( dbmsInfo ) )
		status = dbmsStaticUpdate(

⌨️ 快捷键说明

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