dbxpk15.c

来自「提供了很多种加密算法和CA认证及相关服务如CMP、OCSP等的开发」· C语言 代码 · 共 1,715 行 · 第 1/5 页

C
1,715
字号
		{
		zeroise( pkcs15info->certData, pkcs15info->certDataSize );
		free( pkcs15info->certData );
		}
	if( pkcs15info->dataData != NULL )
		{
		zeroise( pkcs15info->dataData, pkcs15info->dataDataSize );
		free( pkcs15info->dataData );
		}
	zeroise( pkcs15info, sizeof( PKCS15_INFO ) );
	}

void pkcs15Free( PKCS15_INFO *pkcs15info )
	{
	int i;

	for( i = 0; i < MAX_PKCS15_OBJECTS; i++ )
		pkcs15freeEntry( &pkcs15info[ i ] );
	}

/* Get the hash of various certificate name fields */

static int getCertID( const CRYPT_HANDLE iCryptHandle, 
					  CRYPT_ATTRIBUTE_TYPE nameType, BYTE *nameID )
	{
	RESOURCE_DATA msgData;
	BYTE idBuffer[ 1024 ], *idBufPtr = idBuffer;
	int status;

	setResourceData( &msgData, NULL, 0 );
	status = krnlSendMessage( iCryptHandle, RESOURCE_IMESSAGE_GETATTRIBUTE_S,
							  &msgData, nameType );
	if( cryptStatusError( status ) )
		return( CRYPT_ARGERROR_NUM1 );
	if( msgData.length > 1024 && \
		( idBufPtr = malloc( msgData.length ) ) == NULL )
		return( CRYPT_ERROR_MEMORY );
	msgData.data = idBufPtr;
	status = krnlSendMessage( iCryptHandle, RESOURCE_IMESSAGE_GETATTRIBUTE_S, 
							  &msgData, nameType );
	if( cryptStatusOK( status ) )
		{
		HASHFUNCTION hashFunction;
		int hashSize;

		/* Get the hash algorithm information and hash the name to get a name 
		   ID */
		getHashParameters( CRYPT_ALGO_SHA, &hashFunction, &hashSize );
		hashFunction( NULL, nameID, idBufPtr, msgData.length, HASH_ALL );
		}
	if( idBufPtr != idBuffer )
		free( idBufPtr );
	return( status );
	}

/* Get the PKCS #15 validity information from a certificate */

static int getValidityInfo( PKCS15_INFO *pkcs15info, 
							const CRYPT_HANDLE cryptHandle )
	{
	RESOURCE_DATA msgData;
	time_t validFrom, validTo;
	int status;

	/* Remember the validity information for later.  Note that we always
	   update the validity (even if it's already set) since we may be
	   replacing an older cert with a newer one */
	setResourceData( &msgData, &validFrom, sizeof( time_t ) );
	status = krnlSendMessage( cryptHandle, 
							  RESOURCE_IMESSAGE_GETATTRIBUTE_S,
							  &msgData, CRYPT_CERTINFO_VALIDFROM );
	setResourceData( &msgData, &validTo, sizeof( time_t ) );
	if( cryptStatusOK( status ) )
		status = krnlSendMessage( cryptHandle, 
								  RESOURCE_IMESSAGE_GETATTRIBUTE_S,
								  &msgData, CRYPT_CERTINFO_VALIDTO );
	if( cryptStatusError( status ) )
		return( status );
	if( pkcs15info->validTo > validTo )
		/* There's an existing, newer cert already present, make sure we
		   don't try and add the new one */
		return( CRYPT_ERROR_DUPLICATE );
	pkcs15info->validFrom = validFrom;
	pkcs15info->validTo = validTo;
	return( CRYPT_OK );
	}

/****************************************************************************
*																			*
*							Read/Write PKCS #15 Attributes					*
*																			*
****************************************************************************/

/* When writing attributes it's useful to have a fixed-size buffer rather 
   than having to mess around with all sorts of variable-length structures,
   the following value defines the maximum size of the data we can write
   (that is, the I/O stream is opened with this size and generates a
   CRYPT_ERROR_OVERFLOW if we go beyond this).  The maximum-length buffer
   contents are two CRYPT_MAX_TEXTSIZE strings and a few odd bits and pieces
   so this is plenty */

#define KEYATTR_BUFFER_SIZE		256

/* Translate the PKCS #15 usage flags into cryptlib permitted actions.  The
   PKCS #11 use of the 'derive' flag to mean 'allow key agreement' is a bit 
   of a kludge, we map it to allowing keyagreement export and import and if
   there are further constraints they'll be handled by the attached cert.  
   The PKCS #15 nonRepudiation flag doesn't have any definition, so we can't
   do anything with it */

static int getPermittedActions( const int usageFlags )
	{
	int actionFlags = 0;

	if( usageFlags & PKCS15_USAGE_ENCRYPT )
		actionFlags |= MK_ACTION_PERM( RESOURCE_MESSAGE_CTX_ENCRYPT, 
									   ACTION_PERM_NONE_EXTERNAL );
	if( usageFlags & PKCS15_USAGE_DECRYPT )
		actionFlags |= MK_ACTION_PERM( RESOURCE_MESSAGE_CTX_DECRYPT, 
									   ACTION_PERM_NONE_EXTERNAL );
	if( usageFlags & PKCS15_USAGE_SIGN )
		actionFlags |= MK_ACTION_PERM( RESOURCE_MESSAGE_CTX_SIGN, 
									   ACTION_PERM_NONE_EXTERNAL );
	if( usageFlags & PKCS15_USAGE_VERIFY )
		actionFlags |= MK_ACTION_PERM( RESOURCE_MESSAGE_CTX_SIGCHECK, 
									   ACTION_PERM_NONE_EXTERNAL );
	if( usageFlags & PKCS15_USAGE_DERIVE )
		actionFlags |= MK_ACTION_PERM( RESOURCE_MESSAGE_CTX_ENCRYPT, 
									   ACTION_PERM_NONE_EXTERNAL ) | \
					   MK_ACTION_PERM( RESOURCE_MESSAGE_CTX_DECRYPT, 
									   ACTION_PERM_NONE_EXTERNAL );

	return( !actionFlags ? CRYPT_ERROR_PERMISSION : actionFlags );
	}

/* Read a sequence of PKCS #15 key identifiers */

static int readKeyIdentifiers( STREAM *stream, PKCS15_INFO *pkcs15info,
							   const int length )
	{
	const int endPos = ( int ) stell( stream ) + length;
	int status = CRYPT_OK;

	while( !cryptStatusError( status ) && stell( stream ) < endPos )
		{
		HASHFUNCTION hashFunction;
		void *iAndSPtr;
		long value;
		int hashSize, payloadLength, iAndSLength;

		/* Read each identifier type and copy the useful ones into the PKCS
		   #15 info */
		readSequence( stream, &payloadLength );
		status = readShortInteger( stream, &value );
		if( cryptStatusError( status ) )
			break;
		switch( value )
			{
			case PKCS15_KEYID_ISSUERANDSERIALNUMBER:
				/* Hash the full issuerAndSerialNumber to get an iAndSID */
				getHashParameters( CRYPT_ALGO_SHA, &hashFunction, &hashSize );
				iAndSPtr = sMemBufPtr( stream );
				readSequence( stream, &iAndSLength );
				status = sSkip( stream, iAndSLength );
				if( cryptStatusError( status ) )
					break;
				hashFunction( NULL, ( BYTE * ) pkcs15info->iAndSID, iAndSPtr,
							  ( int ) sizeofObject( iAndSLength ), HASH_ALL );
				pkcs15info->iAndSIDlength = hashSize;
				break;

			case PKCS15_KEYID_SUBJECTKEYIDENTIFIER:
				status = readOctetString( stream, pkcs15info->keyID, 
								&pkcs15info->keyIDlength, CRYPT_MAX_HASHSIZE );
				break;

			case PKCS15_KEYID_ISSUERANDSERIALNUMBERHASH:
				/* If we've already got the iAndSID by hashing the 
				   issuerAndSerialNumber, use that version instead */
				if( pkcs15info->iAndSIDlength )
					{
					readUniversal( stream );
					continue;
					}
				status = readOctetString( stream, pkcs15info->iAndSID, 
								&pkcs15info->iAndSIDlength, KEYID_SIZE );
				break;

			case PKCS15_KEYID_ISSUERNAMEHASH:
				status = readOctetString( stream, pkcs15info->issuerNameID, 
								&pkcs15info->issuerNameIDlength, KEYID_SIZE );
				break;

			case PKCS15_KEYID_SUBJECTNAMEHASH:
				status = readOctetString( stream, pkcs15info->subjectNameID, 
								&pkcs15info->subjectNameIDlength, KEYID_SIZE );
				break;

			case PKCS15_KEYID_PGP2:
				status = readOctetString( stream, pkcs15info->pgp2KeyID, 
								&pkcs15info->pgp2KeyIDlength, PGP_KEYID_SIZE );
				break;
			
			case PKCS15_KEYID_OPENPGP:
				status = readOctetString( stream, pkcs15info->openPGPKeyID, 
								&pkcs15info->openPGPKeyIDlength, PGP_KEYID_SIZE );
				break;

			default:
				status = readUniversal( stream );
			}
		}

	return( status );
	}

/* Read an object's attributes */

static int readObjectAttributes( STREAM *stream, PKCS15_INFO *pkcs15info,
								 const PKCS15_OBJECT_TYPE type )
	{
	int length, endPos, status;

	/* Clear the return value */
	memset( pkcs15info, 0, sizeof( PKCS15_INFO ) );

	/* Skip the outer header (this has already been checked when we read in 
	   the object data */
	readTag( stream );
	readShortLength( stream );

	/* Process the PKCS15CommonObjectAttributes */
	status = readSequence( stream, &length );
	if( cryptStatusOK( status ) && length > 0 )
		{
		endPos = ( int ) stell( stream ) + length;

		/* Read the label if it's present and skip anything else */
		if( peekTag( stream ) == BER_STRING_UTF8 )
			status = readOctetStringTag( stream, 
						( BYTE * ) pkcs15info->label, &pkcs15info->labelLength, 
						CRYPT_MAX_TEXTSIZE, BER_STRING_UTF8 );
		if( cryptStatusOK( status ) && stell( stream ) < endPos )
			status = sseek( stream, endPos );
		}
	if( cryptStatusError( status ) )
		return( status );

	/* Process the PKCS15CommonXXXAttributes */
	readSequence( stream, &length );
	endPos = ( int ) stell( stream ) + length;
	if( type == PKCS15_OBJECT_DATA )
		{
		/* It's a data object, make sure it's one of ours */
		status = readOID( stream, OID_CRYPTLIB_CONTENTTYPE );
		if( cryptStatusOK( status ) && stell( stream ) < endPos )
			status = sseek( stream, endPos );
		}
	else
		{
		/* It's a key or cert object, read the ID and assorted flags */
		status = readOctetString( stream, pkcs15info->iD, 
								  &pkcs15info->iDlength, CRYPT_MAX_HASHSIZE );
		if( cryptStatusError( status ) )
			return( status );
		if( type == PKCS15_OBJECT_PUBKEY || type == PKCS15_OBJECT_PRIVKEY )
			{
			int usageFlags;
														/* Usage flags */
			readBitString( stream, &usageFlags );
			if( peekTag( stream ) == BER_BOOLEAN )		/* Native flag */
				status = readUniversal( stream );
			if( stell( stream ) < endPos &&				/* Access flags */
				peekTag( stream ) == BER_BITSTRING )
				status = readUniversal( stream );
			if( type == PKCS15_OBJECT_PUBKEY )
				pkcs15info->pubKeyUsage = usageFlags;
			else
				pkcs15info->privKeyUsage = usageFlags;
			}
		else
			if( type == PKCS15_OBJECT_CERT )
				{
				if( peekTag( stream ) == BER_BOOLEAN )	/* Authority flag */
					status = readUniversal( stream );
				if( stell( stream ) < endPos &&			/* Identifier */
					peekTag( stream ) == BER_SEQUENCE )
					status = readUniversal( stream );
				if( stell( stream ) < endPos &&			/* Thumbprint */
					peekTag( stream ) == MAKE_CTAG( CTAG_CA_DUMMY ) )
					status = readUniversal( stream );
				if( stell( stream ) < endPos &&
					peekTag( stream ) == MAKE_CTAG( CTAG_CA_TRUSTED_USAGE ) )
					{									/* Trusted usage */
					readConstructed( stream, NULL, CTAG_CA_TRUSTED_USAGE );
					status = readBitString( stream, &pkcs15info->trustedUsage );
					}
				if( stell( stream ) < endPos && \
					peekTag( stream ) == MAKE_CTAG( CTAG_CA_IDENTIFIERS ) )
					{									/* Identifiers */
					readConstructed( stream, &length, CTAG_CA_IDENTIFIERS );
					status = readKeyIdentifiers( stream, pkcs15info, length );
					}
				if( stell( stream ) < endPos && peekTag( stream ) == \
							MAKE_CTAG_PRIMITIVE( CTAG_CA_TRUSTED_IMPLICIT ) )
					status = readBooleanTag( stream,
								&pkcs15info->implicitTrust,
								MAKE_CTAG_PRIMITIVE( CTAG_CA_TRUSTED_IMPLICIT ) );
				}
		if( cryptStatusOK( status ) && stell( stream ) < endPos )
			status = sseek( stream, endPos );
		}
	if( cryptStatusError( status ) )
		return( status );

	/* For now we use the iD as the keyID, this may be overridden later if 
	   there's a real keyID present */
	memcpy( pkcs15info->keyID, pkcs15info->iD, pkcs15info->iDlength );
	pkcs15info->keyIDlength = pkcs15info->iDlength;

	/* Skip the public/private key attributes if present */
	if( peekTag( stream ) == MAKE_CTAG( CTAG_OB_SUBCLASSATTR ) )
		status = readUniversal( stream );
	if( cryptStatusError( status ) )
		return( status );
	
	/* Process the type attributes, which just consists of remembering where 
	   the payload starts */
	readConstructed( stream, NULL, CTAG_OB_TYPEATTR );
	status = readSequence( stream, &length );
	endPos = ( int ) stell( stream ) + length;
	if( cryptStatusOK( status ) )
		{
		int value;

		switch( type )
			{
			case PKCS15_OBJECT_PUBKEY:
				readConstructed( stream, NULL, CTAG_OV_DIRECT );
				pkcs15info->pubKeyOffset = ( int ) stell( stream );
				break;

			case PKCS15_OBJECT_PRIVKEY:

⌨️ 快捷键说明

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