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

📄 pkcs15_rd.c

📁 cryptlib是功能强大的安全工具集。允许开发人员快速在自己的软件中集成加密和认证服务。
💻 C
📖 第 1 页 / 共 3 页
字号:
int readKeyset( STREAM *stream, PKCS15_INFO *pkcs15info, const long endPos )
	{
	int status = CRYPT_OK;

	/* Scan all the objects in the file.  We allow a bit of slop to handle
	   incorrect length encodings */
	while( cryptStatusOK( status ) && \
		   stell( stream ) < endPos - MIN_OBJECT_SIZE )
		{
		const int tag = peekTag( stream );
		const PKCS15_OBJECT_TYPE type = EXTRACT_CTAG( tag );
		long innerEndPos;

		/* Read the [n] [0] wrapper to find out what we're dealing with.  We
		   use the long form since keysets with large numbers of objects can
		   grow larger than the maximum size allowed by the standard form */
		if( type < 0 || type >= PKCS15_OBJECT_LAST )
			{
			status = CRYPT_ERROR_BADDATA;
			break;
			}
		readLongConstructed( stream, NULL, tag );
		status = readLongConstructed( stream, &innerEndPos, CTAG_OV_DIRECT );
		if( cryptStatusError( status ) )
			break;
		innerEndPos += stell( stream );
		if( innerEndPos < 16 || innerEndPos > MAX_INTLENGTH )
			return( CRYPT_ERROR_BADDATA );	/* Safety check */

		/* Scan all objects of this type, again allowing for slop */
		while( cryptStatusOK( status ) && \
			   stell( stream ) < innerEndPos - MIN_OBJECT_SIZE )
			{
			PKCS15_INFO pkcs15objectInfo, *pkcs15infoPtr;
			BYTE buffer[ 16 ];
			void *objectData;
			int headerSize, objectLength;

			/* Read the current object.  We can't use getObjectLength() here
			   because we're reading from a file rather than a memory stream */
			status = sread( stream, buffer, 16 );
			if( !cryptStatusError( status ) )	/* sread() returns length */
				status = ( status == 16 || status == CRYPT_OK ) ? \
						 CRYPT_OK : CRYPT_ERROR_UNDERFLOW;
			if( cryptStatusOK( status ) )
				{
				STREAM headerStream;

				sMemConnect( &headerStream, buffer, 16 );
				status = readGenericHole( &headerStream, &objectLength, 
										  DEFAULT_TAG );
				headerSize = stell( &headerStream );
				sMemDisconnect( &headerStream );
				}
			if( cryptStatusOK( status ) && \
				( objectLength < MIN_OBJECT_SIZE || \
				  objectLength > MAX_PRIVATE_KEYSIZE + 1024 ) )
				status = CRYPT_ERROR_BADDATA;
			if( cryptStatusOK( status ) )
				{
				objectLength += headerSize;
				if( ( objectData = clAlloc( "readKeyset", \
											objectLength ) ) == NULL )
					status = CRYPT_ERROR_MEMORY;
				}
			if( cryptStatusError( status ) )
				break;
			memcpy( objectData, buffer, 16 );
			status = sread( stream, ( BYTE * ) objectData + 16, 
							objectLength - 16 );
			if( !cryptStatusError( status ) )	/* sread() returns length */
				status = checkObjectEncoding( objectData, objectLength );
			if( !cryptStatusError( status ) )	/* cOE() returns length */
				{
				STREAM objectStream;

				sMemConnect( &objectStream, objectData, objectLength );
				status = readObjectAttributes( &objectStream,
											   &pkcs15objectInfo, type );
				sMemDisconnect( &objectStream );
				}
			if( cryptStatusError( status ) )
				{
				clFree( "readKeyset", objectData );
				break;
				}

			/* Find out where to add the object data */
			pkcs15infoPtr = findEntry( pkcs15info, CRYPT_KEYIDEX_ID,
									   pkcs15objectInfo.iD,
									   pkcs15objectInfo.iDlength,
									   KEYMGMT_FLAG_NONE );
			if( pkcs15infoPtr == NULL )
				{
				int i;

				/* This personality isn't present yet, find out where we can
				   add the object data and copy the fixed information
				   over */
				for( i = 0; i < MAX_PKCS15_OBJECTS; i++ )
					if( pkcs15info[ i ].type == PKCS15_SUBTYPE_NONE )
						break;
				if( i == MAX_PKCS15_OBJECTS )
					{
					clFree( "readKeyset", objectData );
					status = CRYPT_ERROR_OVERFLOW;
					break;
					}
				pkcs15info[ i ] = pkcs15objectInfo;
				pkcs15infoPtr = &pkcs15info[ i ];
				pkcs15infoPtr->index = i;
				}

			/* If any new ID information has become available, copy it over.
			   The keyID defaults to the iD, so we only copy the newly-read
			   keyID over if it's something other than the existing iD */
			if( pkcs15infoPtr->iDlength != pkcs15objectInfo.keyIDlength || \
				memcmp( pkcs15infoPtr->iD, pkcs15objectInfo.keyID,
						pkcs15objectInfo.keyIDlength ) )
				{
				memcpy( pkcs15infoPtr->keyID, pkcs15objectInfo.keyID,
						pkcs15objectInfo.keyIDlength );
				pkcs15infoPtr->keyIDlength = pkcs15objectInfo.keyIDlength;
				}
			if( pkcs15objectInfo.iAndSIDlength )
				{
				memcpy( pkcs15infoPtr->iAndSID, pkcs15objectInfo.iAndSID,
						pkcs15objectInfo.iAndSIDlength );
				pkcs15infoPtr->iAndSIDlength = pkcs15objectInfo.iAndSIDlength;
				}
			if( pkcs15objectInfo.subjectNameIDlength )
				{
				memcpy( pkcs15infoPtr->subjectNameID,
						pkcs15objectInfo.subjectNameID,
						pkcs15objectInfo.subjectNameIDlength );
				pkcs15infoPtr->subjectNameIDlength = \
						pkcs15objectInfo.subjectNameIDlength;
				}
			if( pkcs15objectInfo.issuerNameIDlength )
				{
				memcpy( pkcs15infoPtr->issuerNameID,
						pkcs15objectInfo.issuerNameID,
						pkcs15objectInfo.issuerNameIDlength );
				pkcs15infoPtr->issuerNameIDlength = \
						pkcs15objectInfo.issuerNameIDlength;
				}
			if( pkcs15objectInfo.pgp2KeyIDlength )
				{
				memcpy( pkcs15infoPtr->pgp2KeyID,
						pkcs15objectInfo.pgp2KeyID,
						pkcs15objectInfo.pgp2KeyIDlength );
				pkcs15infoPtr->pgp2KeyIDlength = \
						pkcs15objectInfo.pgp2KeyIDlength;
				}
			if( pkcs15objectInfo.openPGPKeyIDlength )
				{
				memcpy( pkcs15infoPtr->openPGPKeyID,
						pkcs15objectInfo.openPGPKeyID,
						pkcs15objectInfo.openPGPKeyIDlength );
				pkcs15infoPtr->openPGPKeyIDlength = \
						pkcs15objectInfo.openPGPKeyIDlength;
				}

			/* Copy over any other new information that may have become 
			   available.  The semantics when multiple date ranges are 
			   present (for example one for a key, one for a cert) are a 
			   bit uncertain, we use the most recent date available on the 
			   assumption that this reflects the newest information */
			if( pkcs15objectInfo.validFrom > pkcs15infoPtr->validFrom )
				pkcs15infoPtr->validFrom = pkcs15objectInfo.validFrom;
			if( pkcs15objectInfo.validTo > pkcs15infoPtr->validTo )
				pkcs15infoPtr->validTo = pkcs15objectInfo.validTo;

			/* Copy the payload over */
			switch( type )
				{
				case PKCS15_OBJECT_PUBKEY:
					pkcs15infoPtr->type = PKCS15_SUBTYPE_NORMAL;
					pkcs15infoPtr->pubKeyData = objectData;
					pkcs15infoPtr->pubKeyDataSize = objectLength;
					pkcs15infoPtr->pubKeyOffset = pkcs15objectInfo.pubKeyOffset;
					pkcs15infoPtr->pubKeyUsage = pkcs15objectInfo.pubKeyUsage;
					break;

				case PKCS15_OBJECT_PRIVKEY:
					pkcs15infoPtr->type = PKCS15_SUBTYPE_NORMAL;
					pkcs15infoPtr->privKeyData = objectData;
					pkcs15infoPtr->privKeyDataSize = objectLength;
					pkcs15infoPtr->privKeyOffset = pkcs15objectInfo.privKeyOffset;
					pkcs15infoPtr->privKeyUsage = pkcs15objectInfo.privKeyUsage;
					break;

				case PKCS15_OBJECT_CERT:
				case PKCS15_OBJECT_TRUSTEDCERT:
				case PKCS15_OBJECT_USEFULCERT:
					if( pkcs15infoPtr->type == PKCS15_SUBTYPE_NONE )
						pkcs15infoPtr->type = PKCS15_SUBTYPE_CERT;
					pkcs15infoPtr->certData = objectData;
					pkcs15infoPtr->certDataSize = objectLength;
					pkcs15infoPtr->certOffset = pkcs15objectInfo.certOffset;
					pkcs15infoPtr->trustedUsage = pkcs15objectInfo.trustedUsage;
					pkcs15infoPtr->implicitTrust = pkcs15objectInfo.implicitTrust;
					break;

				case PKCS15_OBJECT_SECRETKEY:
					assert( NOTREACHED );

				case PKCS15_OBJECT_DATA:
					pkcs15infoPtr->type = PKCS15_SUBTYPE_DATA;
					pkcs15infoPtr->dataType = pkcs15objectInfo.dataType;
					pkcs15infoPtr->dataData = objectData;
					pkcs15infoPtr->dataDataSize = objectLength;
					pkcs15infoPtr->dataOffset = pkcs15objectInfo.dataOffset;
					break;
				}
			}
		}

	return( status );
	}

/****************************************************************************
*																			*
*									Read a Key								*
*																			*
****************************************************************************/

/* Set any optional attributes that may be associated with a key */

static int setKeyAttributes( const CRYPT_HANDLE iCryptHandle, 
							 const PKCS15_INFO *pkcs15infoPtr,
							 const int actionFlags )
	{
	RESOURCE_DATA msgData;
	int status = CRYPT_OK;

	if( actionFlags != CRYPT_UNUSED )
		status = krnlSendMessage( iCryptHandle, IMESSAGE_SETATTRIBUTE, 
								  ( void * ) &actionFlags,
								  CRYPT_IATTRIBUTE_ACTIONPERMS );
	if( cryptStatusOK( status ) && pkcs15infoPtr->openPGPKeyIDlength )
		{
		setMessageData( &msgData, ( void * ) pkcs15infoPtr->openPGPKeyID,
						pkcs15infoPtr->openPGPKeyIDlength );
		status = krnlSendMessage( iCryptHandle, IMESSAGE_SETATTRIBUTE_S, 
								  &msgData, CRYPT_IATTRIBUTE_KEYID_OPENPGP );
		}
	if( cryptStatusOK( status ) && pkcs15infoPtr->validFrom )
		{
		setMessageData( &msgData, ( void * ) &pkcs15infoPtr->validFrom,
						sizeof( time_t ) );
		status = krnlSendMessage( iCryptHandle, IMESSAGE_SETATTRIBUTE_S, 
								  &msgData, CRYPT_IATTRIBUTE_PGPVALIDITY );
		}
	return( status );
	}

/* Read the decryption information for the encrypted private key and use it
   to import the encrypted private components into an existing PKC context */

static int readEncryptedKey( STREAM *stream,
							 const CRYPT_CONTEXT iPrivateKey,
							 const char *password, const int passwordLength )
	{
	CRYPT_CONTEXT iSessionKey;
	MESSAGE_CREATEOBJECT_INFO createInfo;
	MECHANISM_WRAP_INFO mechanismInfo;
	RESOURCE_DATA msgData;
	QUERY_INFO queryInfo, contentQueryInfo;
	void *encryptedKey;
	int status;

	/* Skip the 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 */
	readShortInteger( stream, NULL );
	readSet( stream, NULL );
	status = queryAsn1Object( stream, &queryInfo );
	if( cryptStatusError( status ) )
		return( status );
	if( queryInfo.type != CRYPT_OBJECT_ENCRYPTED_KEY )
		return( CRYPT_ERROR_BADDATA );
	encryptedKey = sMemBufPtr( stream );
	readUniversal( stream );	/* Skip the exported key */

	/* Read the session key information into a context */
	status = readCMSencrHeader( stream, dataOIDinfo, &iSessionKey, 
								&contentQueryInfo );
	if( cryptStatusError( status ) )
		return( status );
	if( contentQueryInfo.size > sMemDataLeft( stream ) )
		return( CRYPT_ERROR_UNDERFLOW );

	/* Create an encryption context and 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( cryptStatusOK( 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 = iCryptImportKeyEx( encryptedKey, queryInfo.size,
										CRYPT_FORMAT_CRYPTLIB, 
										createInfo.cryptHandle, iSessionKey,
										NULL );
		krnlSendNotifier( createInfo.cryptHandle, IMESSAGE_DECREFCOUNT );
		}
	memset( &queryInfo, 0, sizeof( QUERY_INFO ) );
	if( cryptStatusError( status ) )
		{
		krnlSendNotifier( iSessionKey, IMESSAGE_DECREFCOUNT );
		return( cryptArgError( status ) ? CRYPT_ERROR_BADDATA : status );
		}

	/* Import the encrypted key into the PKC context */
	setMechanismWrapInfo( &mechanismInfo, sMemBufPtr( stream ),
						  contentQueryInfo.size, NULL, 0, iPrivateKey,
						  iSessionKey, CRYPT_UNUSED );
	status = krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_DEV_IMPORT, 
							  &mechanismInfo, MECHANISM_PRIVATEKEYWRAP );
	clearMechanismInfo( &mechanismInfo );
	krnlSendNotifier( iSessionKey, IMESSAGE_DECREFCOUNT );

	return( status );
	}

/* Return an encoded configuration item */

static int getConfigItem( KEYSET_INFO *keysetInfo,
						  const CRYPT_ATTRIBUTE_TYPE dataType,
						  void *data, int *dataLength )
	{
	const PKCS15_INFO *pkcs15infoPtr = keysetInfo->keyData;
	static int trustedCertIndex;

	assert( dataType == CRYPT_IATTRIBUTE_CONFIGDATA || \
			dataType == CRYPT_IATTRIBUTE_USERINDEX || \
			dataType == CRYPT_IATTRIBUTE_USERINFO || \
			dataType == CRYPT_IATTRIBUTE_TRUSTEDCERT || \
			dataType == CRYPT_IATTRIBUTE_TRUSTEDCERT_NEXT );

	/* If we're being asked for pre-encoded data, return it to the caller */
	if( dataType == CRYPT_IATTRIBUTE_CONFIGDATA || \
		dataType == CRYPT_IATTRIBUTE_USERINDEX || \
		dataType == CRYPT_IATTRIBUTE_USERINFO )
		{
		int length, i;

		/* Find the particular data type we're looking for */

⌨️ 快捷键说明

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