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

📄 pkcs15_rd.c

📁 cryptlib安全工具包
💻 C
📖 第 1 页 / 共 3 页
字号:
	if( pkcs15infoPtr->certData != NULL )
		{
		/* There's a certificate present, import it and reconstruct the
		   public-key information from it if we're creating a partial PKC 
		   context */
		status = iCryptImportCertIndirect( &iCryptContext,
								iCryptKeysetCallback, keyIDtype, keyID,
								keyIDlength, publicComponentsOnly ? \
									KEYMGMT_FLAG_NONE : \
									KEYMGMT_FLAG_DATAONLY_CERT );
		if( cryptStatusError( status ) )
			{
			retExt( status, 
					( status, errorInfo, 
					  "Couldn't recreate certificate from stored "
					  "certificate data" ) );
			}
		if( !publicComponentsOnly )
			{
			DYNBUF pubKeyDB;

			/* We got the certificate, now create the public part of the 
			   context from the certificate's encoded public-key 
			   components */
			iDataCert = iCryptContext;
			status = dynCreate( &pubKeyDB, iDataCert, 
								CRYPT_IATTRIBUTE_SPKI );
			if( cryptStatusError( status ) )
				return( status );
			sMemConnect( &stream, dynData( pubKeyDB ),
						 dynLength( pubKeyDB ) );
			status = iCryptReadSubjectPublicKey( &stream, &iCryptContext,
												 TRUE );
			sMemDisconnect( &stream );
			dynDestroy( &pubKeyDB );
			if( cryptStatusError( status ) )
				{
				krnlSendNotifier( iDataCert, IMESSAGE_DECREFCOUNT );
				retExt( status, 
						( status, errorInfo, 
						  "Couldn't recreate public key from "
						  "certificate" ) );
				}
			}
		}
	else
		{
		const int pubKeyStartOffset = pkcs15infoPtr->pubKeyOffset;
		const int pubKeyTotalSize = pkcs15infoPtr->pubKeyDataSize;

		/* There's no certificate present, create the public-key context
		   directly */
		REQUIRES( rangeCheck( pubKeyStartOffset, 
							  pubKeyTotalSize - pubKeyStartOffset,
							  pubKeyTotalSize ) );
		sMemConnect( &stream, 
					 ( BYTE * ) pkcs15infoPtr->pubKeyData + pubKeyStartOffset,
					 pubKeyTotalSize - pubKeyStartOffset );
		status = iCryptReadSubjectPublicKey( &stream, &iCryptContext,
											 !publicComponentsOnly );
		sMemDisconnect( &stream );
		if( cryptStatusError( status ) )
			{
			retExt( status, 
					( status, errorInfo, 
					  "Couldn't recreate public key from stored public key "
					  "data" ) );
			}
		}

	/* Get the permitted usage flags for each object type that we'll be
	   instantiating.  If there's a public key present we apply its usage
	   flags to whichever PKC context we create, even if it's done indirectly
	   via the certificate import.  Since the private key can also perform 
	   the actions of the public key we set its action flags to the union of 
	   the two */
	status = krnlSendMessage( iCryptContext, IMESSAGE_GETATTRIBUTE,
							  &cryptAlgo, CRYPT_CTXINFO_ALGO );
	if( cryptStatusOK( status ) && pkcs15infoPtr->pubKeyData != NULL )
		{
		status = getPermittedActions( pkcs15infoPtr->pubKeyUsage, cryptAlgo,
									  pubkeyActionFlags );
		}
	if( cryptStatusOK( status ) && !publicComponentsOnly )
		{
		status = getPermittedActions( pkcs15infoPtr->privKeyUsage, cryptAlgo,
									  privkeyActionFlags );
		}
	if( cryptStatusError( status ) )
		{
		krnlSendNotifier( iCryptContext, IMESSAGE_DECREFCOUNT );
		if( iDataCert != CRYPT_ERROR )
			krnlSendNotifier( iDataCert, IMESSAGE_DECREFCOUNT );
		retExt( status, 
				( status, errorInfo, 
				  "Public/private key usage flags don't allow any type of "
				  "key usage" ) );
		}

	/* Return the newly-created objects to the caller */
	*iCryptContextPtr = iCryptContext;
	*iDataCertPtr = iDataCert;
	return( CRYPT_OK );
	}

/****************************************************************************
*																			*
*						Read Public/Private Key Components					*
*																			*
****************************************************************************/

/* Read private-key components from a PKCS #15 object entry */

CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 5 ) ) \
int readPrivateKeyComponents( const PKCS15_INFO *pkcs15infoPtr,
							  IN_HANDLE const CRYPT_CONTEXT iCryptContext,
							  IN_BUFFER( passwordLength ) const void *password, 
							  IN_LENGTH_NAME const int passwordLength, 
							  INOUT ERROR_INFO *errorInfo )
	{
	CRYPT_CONTEXT iSessionKey;
	MESSAGE_CREATEOBJECT_INFO createInfo;
	MECHANISM_WRAP_INFO mechanismInfo;
	MESSAGE_DATA msgData;
	QUERY_INFO queryInfo, contentQueryInfo;
	STREAM stream;
	const int privKeyStartOffset = pkcs15infoPtr->privKeyOffset;
	const int privKeyTotalSize = pkcs15infoPtr->privKeyDataSize;
	void *encryptedKey, *encryptedContent = DUMMY_INIT_PTR;
	int encryptedContentLength = DUMMY_INIT;
	int tag, status;

	assert( isReadPtr( pkcs15infoPtr, sizeof( PKCS15_INFO ) ) );
	assert( isReadPtr( password, passwordLength ) );

	REQUIRES( isHandleRangeValid( iCryptContext ) );
	REQUIRES( passwordLength >= MIN_NAME_LENGTH && \
			  passwordLength < MAX_ATTRIBUTE_SIZE );
	REQUIRES( errorInfo != NULL );

	/* Skip the outer wrapper, version number, and header for the SET OF 
	   EncryptionInfo, and query the exported key information to determine 
	   the parameters required to reconstruct the decryption key */
	REQUIRES( rangeCheck( privKeyStartOffset, 
						  privKeyTotalSize - privKeyStartOffset,
						  privKeyTotalSize ) );
	sMemConnect( &stream,
				 ( BYTE * ) pkcs15infoPtr->privKeyData + privKeyStartOffset,
				 privKeyTotalSize - privKeyStartOffset );
	tag = status = peekTag( &stream );
	if( cryptStatusError( status ) )
		return( status );
	if( tag == CTAG_OV_FUTUREUSE )
		{
		/* Future versions of cryptlib will use AuthEnvelopedData to protect
		   keys which will presumably be identified with a new tag because
		   CTAG_OV_DIRECTPROTECTED implies EnvelopedData.  For forwards-
		   compatibility we check for this tag and warn the user about it */
		retExt( CRYPT_ERROR_NOTAVAIL, 
				( CRYPT_ERROR_NOTAVAIL, errorInfo, 
				  "Key is protected using AuthEnvelopedData, this requires "
				  "a newer version of cryptlib to process" ) );
		}
	readConstructed( &stream, NULL, CTAG_OV_DIRECTPROTECTED );
	readShortInteger( &stream, NULL );
	readSet( &stream, NULL );
	status = queryAsn1Object( &stream, &queryInfo );
	if( cryptStatusOK( status ) && \
		queryInfo.type != CRYPT_OBJECT_ENCRYPTED_KEY )
		status = CRYPT_ERROR_BADDATA;
	if( cryptStatusError( status ) )
		{
		sMemDisconnect( &stream );
		zeroise( &queryInfo, sizeof( QUERY_INFO ) );
		retExt( status, 
				( status, errorInfo, 
				  "Invalid encrypted key data header" ) );
		}
	status = sMemGetDataBlock( &stream, &encryptedKey, queryInfo.size );
	if( cryptStatusOK( status ) )
		status = readUniversal( &stream );	/* Skip the exported key */
	if( cryptStatusError( status ) )
		{
		sMemDisconnect( &stream );
		zeroise( &queryInfo, sizeof( QUERY_INFO ) );
		return( status );
		}

	/* Read the header for the encrypted key and make sure that all of the
	   data is present in the stream */
	status = readCMSencrHeader( &stream, dataOIDinfo, 
								FAILSAFE_ARRAYSIZE( dataOIDinfo, OID_INFO ), 
								&iSessionKey, &contentQueryInfo );
	if( cryptStatusOK( status ) )
		{
		encryptedContentLength = contentQueryInfo.size;
		status = sMemGetDataBlock( &stream, &encryptedContent, 
								   encryptedContentLength );
		if( cryptStatusOK( status ) && \
			( encryptedContentLength == CRYPT_UNUSED || \
			  encryptedContentLength < MIN_OBJECT_SIZE || \
			  encryptedContentLength > MAX_INTLENGTH_SHORT ) )
			{
			/* Indefinite length or too-small object */
			status = CRYPT_ERROR_BADDATA;
			}
		}
	zeroise( &contentQueryInfo, sizeof( QUERY_INFO ) );
	sMemDisconnect( &stream );
	if( cryptStatusError( status ) )
		{
		zeroise( &queryInfo, sizeof( QUERY_INFO ) );
		retExt( status, 
				( status, errorInfo, "Invalid encrypted key data header" ) );
		}

	/* Create an encryption context, derive the user password into it using 
	   the given parameters, and import the session key.  If there's an 
	   error in the parameters stored with the exported key we'll get an arg 
	   or attribute error when we try to set the attribute so we translate 
	   it into an error code which is appropriate for the situation */
	setMessageCreateObjectInfo( &createInfo, queryInfo.cryptAlgo );
	status = krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_DEV_CREATEOBJECT,
							  &createInfo, OBJECT_TYPE_CONTEXT );
	if( cryptStatusError( status ) )
		{
		zeroise( &queryInfo, sizeof( QUERY_INFO ) );
		return( status );
		}
	status = krnlSendMessage( createInfo.cryptHandle, IMESSAGE_SETATTRIBUTE, 
							  &queryInfo.cryptMode, CRYPT_CTXINFO_MODE );
	if( cryptStatusOK( status ) )
		status = krnlSendMessage( createInfo.cryptHandle, IMESSAGE_SETATTRIBUTE,
								  &queryInfo.keySetupAlgo,
								  CRYPT_CTXINFO_KEYING_ALGO );
	if( cryptStatusOK( status ) )
		status = krnlSendMessage( createInfo.cryptHandle, IMESSAGE_SETATTRIBUTE,
								  &queryInfo.keySetupIterations,
								  CRYPT_CTXINFO_KEYING_ITERATIONS );
	if( cryptStatusOK( status ) )
		{
		setMessageData( &msgData, queryInfo.salt, queryInfo.saltLength );
		status = krnlSendMessage( createInfo.cryptHandle, IMESSAGE_SETATTRIBUTE_S, 
								  &msgData, CRYPT_CTXINFO_KEYING_SALT );
		}
	if( cryptStatusOK( status ) )
		{
		setMessageData( &msgData, ( void * ) password, passwordLength );
		status = krnlSendMessage( createInfo.cryptHandle, IMESSAGE_SETATTRIBUTE_S, 
								  &msgData, CRYPT_CTXINFO_KEYING_VALUE );
		}
	if( cryptStatusOK( status ) )
		{
		status = iCryptImportKey( encryptedKey, queryInfo.size,
								  CRYPT_FORMAT_CRYPTLIB, 
								  createInfo.cryptHandle, iSessionKey, NULL );
		}
	krnlSendNotifier( createInfo.cryptHandle, IMESSAGE_DECREFCOUNT );
	zeroise( &queryInfo, sizeof( QUERY_INFO ) );
	if( cryptStatusError( status ) )
		{
		krnlSendNotifier( iSessionKey, IMESSAGE_DECREFCOUNT );
		if( cryptArgError( status ) )
			status = CRYPT_ERROR_BADDATA;
		retExt( status, 
				( status, errorInfo, 
				  "Couldn't create decryption context for private key from "
				  "user password" ) );
		}

	/* Import the encrypted key into the PKC context */
	setMechanismWrapInfo( &mechanismInfo, ( void * ) encryptedContent,
						  encryptedContentLength, NULL, 0, iCryptContext,
						  iSessionKey );
	status = krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_DEV_IMPORT,

⌨️ 快捷键说明

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