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

📄 pgp_env.c

📁 cryptlib是功能强大的安全工具集。允许开发人员快速在自己的软件中集成加密和认证服务。
💻 C
📖 第 1 页 / 共 2 页
字号:
				/* There's no key exchange action, we're using a raw session
				   key derived from a password */
				envelopeInfoPtr->lastAction = envelopeInfoPtr->actionList;
			envelopeInfoPtr->envState = ENVSTATE_KEYINFO;
			}
		else
			{
			STREAM stream;
			int length;

			/* If we're not encrypting data (i.e. there's only a single 
			   packet present rather than a packet preceded by a pile of key
			   exchange actions), write the appropriate PGP header based on 
			   the envelope usage */
			sMemOpen( &stream, envelopeInfoPtr->buffer, 
					  envelopeInfoPtr->bufSize );
			switch( envelopeInfoPtr->usage )
				{
				case ACTION_SIGN:
					if( !( envelopeInfoPtr->flags & ENVELOPE_DETACHED_SIG ) )
						{
						status = writeSignatureInfoPacket( &stream, 
								envelopeInfoPtr->postActionList->iCryptHandle,
								envelopeInfoPtr->actionList->iCryptHandle );
						if( cryptStatusError( status ) )
							break;
						}

					/* Since we can only sign literal data, we need to 
					   explicitly write an inner data header */
					assert( envelopeInfoPtr->contentType == CRYPT_CONTENT_DATA );
					envelopeInfoPtr->envState = ENVSTATE_DATA;
					break;

				case ACTION_NONE:
					/* Write the header followed by an indicator that we're 
					   using opaque content, a zero-length filename, and no 
					   date */
					pgpWritePacketHeader( &stream, PGP_PACKET_DATA, 
						envelopeInfoPtr->payloadSize + PGP_DATA_HEADER_SIZE );
					swrite( &stream, PGP_DATA_HEADER, PGP_DATA_HEADER_SIZE );
					break;

				case ACTION_COMPRESS:
					/* Compressed data packets use a special unkown-length 
					   encoding that doesn't work like any other PGP packet 
					   type, so we can't use pgpWritePacketHeader() for this
					   packet type but have to hand-assemble the header
					   ourselves */
					sputc( &stream, PGP_CTB_COMPRESSED );
					sputc( &stream, PGP_ALGO_ZLIB );
					if( envelopeInfoPtr->contentType == CRYPT_CONTENT_DATA )
						/* If there's no inner content type, we need to 
						   explicitly write an inner data header */
						envelopeInfoPtr->envState = ENVSTATE_DATA;
					break;
	
				default:
					assert( NOTREACHED );
				}
			length = stell( &stream );
			sMemDisconnect( &stream );
			if( cryptStatusError( status ) )
				return( status );
			envelopeInfoPtr->bufPos = length;

			/* Reset the segmentation state.  Although PGP doesn't segment 
			   the payload, we still have to reset the state to synchronise 
			   things like payload hashing and encryption.  We also set the 
			   block size mask to all ones if we're not encrypting, since we 
			   can begin and end data segments on arbitrary boundaries */
			envelopeInfoPtr->dataFlags |= ENVDATA_SEGMENTCOMPLETE;
			if( envelopeInfoPtr->usage != ACTION_CRYPT )
				envelopeInfoPtr->blockSizeMask = -1;
			envelopeInfoPtr->lastAction = NULL;

			/* If we're not emitting any inner header, we're done */
			if( envelopeInfoPtr->envState == ENVSTATE_HEADER || \
				( envelopeInfoPtr->flags & ENVELOPE_DETACHED_SIG ) )
				{
				envelopeInfoPtr->envState = ENVSTATE_DONE;
				return( CRYPT_OK );
				}
			}
		}

	/* Handle key export actions */
	if( envelopeInfoPtr->envState == ENVSTATE_KEYINFO )
		{
		ACTION_LIST *lastActionPtr;

		/* Export the session key using each of the PKC keys, or write the 
		   derivation information needed to recreate the session key */
		for( lastActionPtr = envelopeInfoPtr->lastAction; 
			 lastActionPtr != NULL; lastActionPtr = lastActionPtr->next )
			{
			void *bufPtr = envelopeInfoPtr->buffer + envelopeInfoPtr->bufPos;
			const int dataLeft = min( envelopeInfoPtr->bufSize - \
									  envelopeInfoPtr->bufPos, 8192 );
			int keyexSize;

			/* Make sure that there's enough room to emit this key exchange 
			   action */
			if( lastActionPtr->encodedSize + 128 > dataLeft )
				{
				status = CRYPT_ERROR_OVERFLOW;
				break;
				}

			/* Emit the key exchange action */
			if( lastActionPtr->action == ACTION_KEYEXCHANGE_PKC )
				status = iCryptExportKeyEx( bufPtr, &keyexSize, dataLeft,
								CRYPT_FORMAT_PGP, envelopeInfoPtr->iCryptContext,
								lastActionPtr->iCryptHandle, CRYPT_UNUSED );
			else
				status = iCryptExportKeyEx( bufPtr, &keyexSize, dataLeft,
								CRYPT_FORMAT_PGP, CRYPT_UNUSED, 
								envelopeInfoPtr->iCryptContext, CRYPT_UNUSED );
			if( cryptStatusError( status ) )
				break;
			envelopeInfoPtr->bufPos += keyexSize;
			}
		envelopeInfoPtr->lastAction = lastActionPtr;
		if( cryptStatusError( status ) )
			return( status );

		/* Move on to the next state */
		envelopeInfoPtr->envState = ENVSTATE_ENCRINFO;
		}

	/* Handle encrypted content information */
	if( envelopeInfoPtr->envState == ENVSTATE_ENCRINFO )
		{
		STREAM stream;
		BYTE ivInfoBuffer[ CRYPT_MAX_IVSIZE + 2 ];
		const int dataLeft = min( envelopeInfoPtr->bufSize - \
								  envelopeInfoPtr->bufPos, 8192 );
		int length;

		/* Make sure that there's enough room to emit the encrypted content 
		   header (+4 for slop space) */
		if( dataLeft < PGP_MAX_HEADER_SIZE + PGP_IVSIZE + 2 + 4 )
			return( CRYPT_ERROR_OVERFLOW );

		/* Set up the PGP IV information */
		status = pgpProcessIV( envelopeInfoPtr->iCryptContext, 
							   ivInfoBuffer, PGP_IVSIZE, TRUE, TRUE );
		if( cryptStatusError( status ) )
			return( status );

		/* Write the encrypted content header */
		sMemOpen( &stream, envelopeInfoPtr->buffer + \
						   envelopeInfoPtr->bufPos, dataLeft );
		pgpWritePacketHeader( &stream, PGP_PACKET_ENCR, 
							PGP_IVSIZE + 2 + 1 + \
							pgpSizeofLength( PGP_DATA_HEADER_SIZE + \
											 envelopeInfoPtr->payloadSize ) + \
							PGP_DATA_HEADER_SIZE + \
							envelopeInfoPtr->payloadSize );
		status = swrite( &stream, ivInfoBuffer, PGP_IVSIZE + 2 );
		length = stell( &stream );
		sMemDisconnect( &stream );
		if( cryptStatusError( status ) )
			return( status );
		envelopeInfoPtr->bufPos += length;

		/* Make sure that we start a new segment if we try to add any data */
		envelopeInfoPtr->dataFlags |= ENVDATA_SEGMENTCOMPLETE;

		/* Before we can finish we have to push in the inner data header */
		envelopeInfoPtr->envState = ENVSTATE_DATA;
		}

	/* Handle data payload information */
	if( envelopeInfoPtr->envState == ENVSTATE_DATA )
		{
		STREAM stream;
		BYTE headerBuffer[ 64 ];

		/* Make sure that there's enough room to emit the data header (+4 
		   for slop space) */
		if( envelopeInfoPtr->bufSize - envelopeInfoPtr->bufPos < \
			PGP_MAX_HEADER_SIZE + PGP_DATA_HEADER_SIZE + 4 )
			return( CRYPT_ERROR_OVERFLOW );

		/* Write the payload header.  Since this may be encrypted, we have to
		   do it indirectly via copyToEnvelope() */
		sMemOpen( &stream, headerBuffer, 64 );
		pgpWritePacketHeader( &stream, PGP_PACKET_DATA, 
						PGP_DATA_HEADER_SIZE + envelopeInfoPtr->payloadSize );
		swrite( &stream, PGP_DATA_HEADER, PGP_DATA_HEADER_SIZE );
		if( envelopeInfoPtr->payloadSize != CRYPT_UNUSED )
			/* There's an absolute data length set, adjust the running total 
			   count by the size of the additional header that's been 
			   prepended */
			envelopeInfoPtr->segmentSize += stell( &stream );
		status = envelopeInfoPtr->copyToEnvelopeFunction( envelopeInfoPtr,
											headerBuffer, stell( &stream ) );
		sMemClose( &stream );
		if( cryptStatusError( status ) )
			return( status );

		/* We've processed the header, if this is signed data we start 
		   hashing from this point.  The PGP RFCs are wrong in this regard, 
		   only the payload is hashed, not the entire packet */
		if( envelopeInfoPtr->usage == ACTION_SIGN )
			envelopeInfoPtr->dataFlags |= ENVDATA_HASHACTIONSACTIVE;

		/* We're finished */
		envelopeInfoPtr->envState = ENVSTATE_DONE;
		}

	return( CRYPT_OK );
	}

/* Output as much of the postamble as possible into the envelope buffer */

static int emitPostamble( ENVELOPE_INFO *envelopeInfoPtr )
	{
	int sigBufSize, sigSize, status;

	/* Before we can emit the trailer we need to flush any remaining data
	   from internal buffers */
	if( envelopeInfoPtr->envState == ENVSTATE_NONE )
		{
		status = envelopeInfoPtr->copyToEnvelopeFunction( envelopeInfoPtr, 
														  ( BYTE * ) "", 0 );
		if( cryptStatusError( status ) )
			return( status );
		envelopeInfoPtr->envState = ENVSTATE_FLUSHED;
		}

	/* The only PGP packet that has a trailer is signed data using the new
	   (post-2.x) one-pass signature packet, if we're not signing data we can
	   exit now */
	if( envelopeInfoPtr->usage != ACTION_SIGN )
		{
		/* We're done */
		envelopeInfoPtr->envState = ENVSTATE_DONE;
		return( CRYPT_OK );
		}

	/* Check whether there's enough room left in the buffer to emit the 
	   signature directly into it.  Since sigs are fairly small (a few 
	   hundred bytes), we always require enough room in the buffer and don't 
	   bother with any overflow handling via the auxBuffer */
	sigBufSize = min( envelopeInfoPtr->bufSize - envelopeInfoPtr->bufPos, 
					  8192 );
	if( envelopeInfoPtr->postActionList->encodedSize + 64 > sigBufSize )
		return( CRYPT_ERROR_OVERFLOW );

	/* Sign the data */
	status = iCryptCreateSignatureEx( envelopeInfoPtr->buffer + \
									  envelopeInfoPtr->bufPos, &sigSize, 
									  sigBufSize, CRYPT_FORMAT_PGP, 
									  envelopeInfoPtr->postActionList->iCryptHandle, 
									  envelopeInfoPtr->actionList->iCryptHandle,
									  CRYPT_UNUSED, CRYPT_UNUSED );
	if( cryptStatusError( status ) )
		return( status );
	envelopeInfoPtr->bufPos += sigSize;

	/* Now that we've written the final data, set the end-of-segment-data 
	   pointer to the end of the data in the buffer so that 
	   copyFromEnvelope() can copy out the remaining data */
	envelopeInfoPtr->segmentDataEnd = envelopeInfoPtr->bufPos;
	envelopeInfoPtr->envState = ENVSTATE_DONE;

	return( CRYPT_OK );
	}

/****************************************************************************
*																			*
*							Envelope Access Routines						*
*																			*
****************************************************************************/

void initPGPEnveloping( ENVELOPE_INFO *envelopeInfoPtr )
	{
	/* Set the access method pointers */
	envelopeInfoPtr->processPreambleFunction = emitPreamble;
	envelopeInfoPtr->processPostambleFunction = emitPostamble;
	envelopeInfoPtr->checkCryptAlgo = checkCryptAlgo;
	envelopeInfoPtr->checkHashAlgo = checkHashAlgo;

	/* Set up the processing state information */
	envelopeInfoPtr->envState = ENVSTATE_NONE;

	/* Remember the current default settings for use with the envelope.  
	   Since the PGP algorithms represent only a subset of what's available, 
	   we have to drop back to fixed values if the caller has selected 
	   something exotic */
	krnlSendMessage( envelopeInfoPtr->ownerHandle, 
					 IMESSAGE_GETATTRIBUTE, &envelopeInfoPtr->defaultHash, 
					 CRYPT_OPTION_ENCR_HASH );
	if( cryptlibToPgpAlgo( envelopeInfoPtr->defaultHash ) == PGP_ALGO_NONE )
		envelopeInfoPtr->defaultHash = CRYPT_ALGO_SHA;
	krnlSendMessage( envelopeInfoPtr->ownerHandle, 
					 IMESSAGE_GETATTRIBUTE, &envelopeInfoPtr->defaultAlgo, 
					 CRYPT_OPTION_ENCR_ALGO );
	if( cryptlibToPgpAlgo( envelopeInfoPtr->defaultAlgo ) == PGP_ALGO_NONE )
		envelopeInfoPtr->defaultAlgo = CRYPT_ALGO_3DES;
	envelopeInfoPtr->defaultMAC = CRYPT_ALGO_NONE;

	/* Turn off segmentation of the envelope payload.  PGP has a single 
	   length at the start of the data and doesn't segment the payload */
	envelopeInfoPtr->dataFlags |= ENVDATA_NOSEGMENT;
	}
#endif /* USE_PGP */

⌨️ 快捷键说明

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