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

📄 pkcs12.c

📁 cryptlib是功能强大的安全工具集。允许开发人员快速在自己的软件中集成加密和认证服务。
💻 C
📖 第 1 页 / 共 3 页
字号:
		}

	/* We're ready to go, lock the object for our exclusive use */
	status = krnlSendNotifier( cryptHandle, IMESSAGE_LOCK );
	if( cryptStatusError( status ) )
		return( status );

	/* Write the cert if necessary.  We do this one first because it's the
	   easiest to back out of */
	if( certPresent )
		{
		RESOURCE_DATA msgData;

		/* Select the leaf cert in case it's a cert chain */
		krnlSendMessage( cryptHandle, IMESSAGE_SETATTRIBUTE,
						 MESSAGE_VALUE_CURSORFIRST,
						 CRYPT_CERTINFO_CURRENT_CERTIFICATE );

		/* Get the encoded cert */
		setResourceData( &msgData, NULL, 0 );
		status = krnlSendMessage( cryptHandle, IMESSAGE_GETATTRIBUTE_S,
								  &msgData, CRYPT_IATTRIBUTE_ENC_CERT );
		if( cryptStatusOK( status ) && \
			( pkcs12infoPtr->certData = clAlloc( "setItemFunction", \
												 msgData.length ) ) == NULL )
			status = CRYPT_ERROR_MEMORY;
		if( cryptStatusOK( status ) )
			{
			msgData.data = pkcs12infoPtr->certData;
			status = krnlSendMessage( cryptHandle, IMESSAGE_GETATTRIBUTE_S,
									  &msgData, CRYPT_IATTRIBUTE_ENC_CERT );
			if( cryptStatusOK( status ) )
				pkcs12infoPtr->certDataSize = msgData.length;
			else
				{
				clFree( "setItemFunction", pkcs12infoPtr->certData );
				pkcs12infoPtr->certData = NULL;
				}
			}

		/* If there's no context to add, return now */
		if( cryptStatusError( status ) || pkcs12keyPresent )
			{
			krnlSendNotifier( cryptHandle, IMESSAGE_UNLOCK );
			return( status );
			}
		}

	/* Create the key wrap context and the MAC context (if necessary) from 
	   the password.  See the comment at the start of the file for the 
	   ambiguity involved with the MAC context */
	status = createKeyWrapContext( &iKeyWrapContext, keysetInfo->ownerHandle, 
								   password, passwordLength, pkcs12infoPtr );
	if( cryptStatusOK( status ) && pkcs12infoPtr->iMacContext == CRYPT_ERROR )
		status = createMacContext( pkcs12infoPtr, keysetInfo->ownerHandle, 
								   password, passwordLength );
	if( cryptStatusError( status ) )
		{
		pkcs12freeEntry( pkcs12infoPtr );
		krnlSendNotifier( cryptHandle, IMESSAGE_UNLOCK );
		return( status );
		}

	/* Calculate the eventual encrypted key size and allocate storage for it */
	setMechanismWrapInfo( &mechanismInfo, NULL, 0, NULL, 0, cryptHandle,
						  iKeyWrapContext, CRYPT_UNUSED );
	status = krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_DEV_EXPORT, 
							  &mechanismInfo, MECHANISM_PRIVATEKEYWRAP_PKCS8 );
	privKeyInfoSize = mechanismInfo.wrappedDataLength;
	clearMechanismInfo( &mechanismInfo );
	if( cryptStatusOK( status ) && \
		( pkcs12infoPtr->privKeyData = \
				clAlloc( "setItemFunction", privKeyInfoSize + 64 ) ) == NULL )
			status = CRYPT_ERROR_MEMORY;
	if( cryptStatusError( status ) )
		{
		pkcs12freeEntry( pkcs12infoPtr );
		krnlSendNotifier( iKeyWrapContext, IMESSAGE_DECREFCOUNT );
		krnlSendNotifier( cryptHandle, IMESSAGE_UNLOCK );
		return( status );
		}
	pkcs12infoPtr->privKeyDataSize = privKeyInfoSize + 64;

	/* Write the key-derivation information and wrapped key */
	pbeInfoDataSize = ( int ) sizeofObject( pkcs12infoPtr->wrapSaltSize ) + \
					  sizeofShortInteger( pkcs12infoPtr->wrapIterations );
	sMemOpen( &stream, pkcs12infoPtr->privKeyData,
			  pkcs12infoPtr->privKeyDataSize );
	writeSequence( &stream,
				   sizeofOID( OID_PKCS12_PBEWITHSHAAND2KEYTRIPLEDESCBC ) + \
				   ( int ) sizeofObject( pbeInfoDataSize ) );
	writeOID( &stream, OID_PKCS12_PBEWITHSHAAND2KEYTRIPLEDESCBC );
	writeSequence( &stream, pbeInfoDataSize );
	writeOctetString( &stream, pkcs12infoPtr->wrapSalt, 
					  pkcs12infoPtr->wrapSaltSize, DEFAULT_TAG );
	writeShortInteger( &stream, pkcs12infoPtr->wrapIterations, DEFAULT_TAG );
	writeOctetStringHole( &stream, privKeyInfoSize, DEFAULT_TAG );
	assert( stell( &stream ) < 64 );
	assert( sStatusOK( &stream ) );
	setMechanismWrapInfo( &mechanismInfo,
						  ( BYTE * ) pkcs12infoPtr->privKeyData + \
									 ( int ) stell( &stream ),
						  privKeyInfoSize, NULL, 0, cryptHandle,
						  iKeyWrapContext, CRYPT_UNUSED );
	status = krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_DEV_EXPORT, 
							  &mechanismInfo, MECHANISM_PRIVATEKEYWRAP_PKCS8 );
	if( cryptStatusOK( status ) )
		pkcs12infoPtr->privKeyDataSize = ( int ) stell( &stream ) + \
										 privKeyInfoSize;
	else
		pkcs12freeEntry( pkcs12infoPtr );
	sMemDisconnect( &stream );
	krnlSendNotifier( cryptHandle, IMESSAGE_UNLOCK );

	return( status );
	}

/****************************************************************************
*																			*
*								Init/Shutdown Functions						*
*																			*
****************************************************************************/

/* At one point Netscape produced PKCS #12 files with each primitive portion
   of encapsulated content (T, L, and V) wrapped up in its own constructed
   OCTET STRING segment.  The following function unpacks this mess */

static int unwrapOctetString( STREAM *stream, BYTE *buffer,
							  const int totalLength )
	{
	int bufPos = 0, status;

	while( checkEOC( stream ) != TRUE )
		{
		int length;

		/* Read the current OCTET STRING segment into the buffer */
		status = readOctetStringHole( stream, &length, DEFAULT_TAG );
		if( cryptStatusError( status ) )
			return( status );

		/* Make sure that we don't overshoot the buffer if the length 
		   encodings are wrong */
		if( bufPos + length > totalLength )
			return( CRYPT_ERROR_BADDATA );

		/* Copy in the current segment */
		status = sread( stream, buffer + bufPos, length );
		if( cryptStatusError( status ) )
			return( status );
		bufPos += length;
		}

	return( bufPos );
	}

/* A PKCS #12 file can contain steaming mounds of keys and whatnot, so when we
   open it we scan it and record various pieces of information about it which
   we can use later when we need to access it */

static int initFunction( KEYSET_INFO *keysetInfo, const char *name,
						 const CRYPT_KEYOPT_TYPE options )
	{
	PKCS12_INFO *pkcs12info;
	STREAM *stream = &keysetInfo->keysetFile->stream, memStream;
	BYTE *buffer;
	BOOLEAN isIndefinite = FALSE;
	long length;
	int totalLength, status;

	assert( name == NULL );

	/* Read the outer wrapper, version number field, and CMS data wrapper.  
	   We do this before we perform any setup operations to weed out
	   potential problem files */
	if( options != CRYPT_KEYOPT_CREATE )
		{
		long version;

		readSequence( stream, NULL );
		readShortInteger( stream, &version );
		status = readCMSheader( stream, dataOIDselection, &length, FALSE );
		if( cryptStatusError( status ) )
			return( status );
		if( version != 3 )
			return( CRYPT_ERROR_BADDATA );
		}

	/* Allocate the PKCS #12 object info */
	if( ( pkcs12info = clAlloc( "initFunction", \
								sizeof( PKCS12_INFO ) * \
								MAX_PKCS12_OBJECTS ) ) == NULL )
		return( CRYPT_ERROR_MEMORY );
	memset( pkcs12info, 0, sizeof( PKCS12_INFO ) * MAX_PKCS12_OBJECTS );
	keysetInfo->keyData = pkcs12info;
	keysetInfo->keyDataSize = sizeof( PKCS12_INFO ) * MAX_PKCS12_OBJECTS;
	pkcs12info->iMacContext = CRYPT_ERROR;

	/* If this is a newly-created keyset, there's nothing left to do */
	if( options == CRYPT_KEYOPT_CREATE )
		return( CRYPT_OK );

	/* Extract the OCTET STRING data into an in-memory buffer.  If the file
	   is of a known length we allocate a buffer of that size, otherwise we
	   just try for a reasonable value (indefinite-length encodings are only
	   used by broken older Netscape code which breaks each component up into
	   its own OCTET STRING) */
	if( length == CRYPT_UNUSED )
		{
		totalLength = 8192;
		isIndefinite = TRUE;
		}
	else
		totalLength = ( int ) length;
	if( ( buffer = clAlloc( "initFunction", totalLength ) ) == NULL )
		return( CRYPT_ERROR_MEMORY );
	if( isIndefinite )
		status = totalLength = unwrapOctetString( stream, buffer,
												  totalLength );
	else
		status = sread( stream, buffer, totalLength );
	if( cryptStatusError( status ) )
		{
		clFree( "initFunction", buffer );
		return( status );
		}

	/* Extract the next level of unnecessarily nested data from the mess */
	sMemConnect( &memStream, buffer, totalLength );
	readSequence( &memStream, NULL );
	status = readCMSheader( &memStream, keyDataOIDselection, &length, TRUE );
	if( cryptStatusOK( status ) )
		{
		BYTE *innerBuffer;

		/* If it's straight Data, it'll be a PKCS #8 encrypted nested mess
		   rather than a straight encrypted mess */
		isIndefinite = ( length == CRYPT_UNUSED ) ? TRUE : FALSE;
		if( !isIndefinite )
			totalLength = ( int ) length;
		if( ( innerBuffer = clAlloc( "initFunction", totalLength ) ) != NULL )
			{
			if( isIndefinite )
				{
				status = totalLength = unwrapOctetString( &memStream,
												innerBuffer, totalLength );
				if( !cryptStatusError( status ) )
					status = CRYPT_OK;
				}
			else
				status = sread( stream, innerBuffer, totalLength );

			/* At this point you're on your own - this is too ghastly to
			   continue */

			clFree( "initFunction", innerBuffer );
			}
		}
	sMemDisconnect( &memStream );
	clFree( "initFunction", buffer );

	return( CRYPT_OK );
	}

/* Shut down the PKCS #12 state, flushing information to disk if necessary */

static void shutdownFunction( KEYSET_INFO *keysetInfo )
	{
	/* If the contents have been changed, commit the changes to disk */
	if( keysetInfo->flags & KEYSET_DIRTY )
		{
		int status;

		sseek( &keysetInfo->keysetFile->stream, 0 );
		status = pkcs12Flush( &keysetInfo->keysetFile->stream,
							  keysetInfo->keyData );
		if( status == OK_SPECIAL )
			keysetInfo->flags |= KEYSET_EMPTY;
		}

	/* Free the PKCS #12 object info */
	if( keysetInfo->keyData != NULL )
		{
		pkcs12Free( keysetInfo->keyData );
		zeroise( keysetInfo->keyData, keysetInfo->keyDataSize );
		clFree( "shutdownFunction", keysetInfo->keyData );
		}
	}

/****************************************************************************
*																			*
*							Keyset Access Routines							*
*																			*
****************************************************************************/

int setAccessMethodPKCS12( KEYSET_INFO *keysetInfo )
	{
	/* Set the access method pointers */
	keysetInfo->initFunction = initFunction;
	keysetInfo->shutdownFunction = shutdownFunction;
	keysetInfo->getItemFunction = getItemFunction;
	keysetInfo->setItemFunction = setItemFunction;

	return( CRYPT_OK );
	}
#endif /* USE_PKCS12 */

⌨️ 快捷键说明

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