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

📄 pgp_denv.c

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

				case PGP_PACKET_COPR:
					value = sgetc( &stream );
					if( envelopeInfoPtr->usage != ACTION_NONE )
						{
						status = CRYPT_ERROR_BADDATA;
						break;
						}
					envelopeInfoPtr->usage = ACTION_COMPRESS;
#ifdef USE_COMPRESSION
					if( value == PGP_ALGO_ZIP )
						{
						/* PGP 2.x has a funny compression level based on DOS
						   memory limits (13-bit windows) and no zlib header
						   (because it uses very old InfoZIP code).  Setting
						   the windowSize to a negative value has the
						   undocumented effect of not reading zlib headers */
						if( inflateInit2( &envelopeInfoPtr->zStream, -13 ) == Z_OK )
							envelopeInfoPtr->flags |= ENVELOPE_ZSTREAMINITED;
						else
							status = CRYPT_ERROR_MEMORY;
						}
					else
						if( value == PGP_ALGO_ZLIB )
							{
							/* Standard zlib compression */
							if( inflateInit( &envelopeInfoPtr->zStream ) == Z_OK )
								envelopeInfoPtr->flags |= ENVELOPE_ZSTREAMINITED;
							else
								status = CRYPT_ERROR_MEMORY;
							}
						else
							{
							status = ( value < 0 ) ? \
									 value : CRYPT_ERROR_NOTAVAIL;
							break;
							}
#else
					status = CRYPT_ERROR_NOTAVAIL;
#endif /* USE_COMPRESSION */
					state = PGP_DEENVSTATE_DATA;
					break;

				case PGP_PACKET_SKE:
				case PGP_PACKET_PKE:
					/* Read the SKE/PKE packet */
					if( envelopeInfoPtr->usage != ACTION_NONE && \
						envelopeInfoPtr->usage != ACTION_CRYPT )
						{
						status = CRYPT_ERROR_BADDATA;
						break;
						}
					envelopeInfoPtr->usage = ACTION_CRYPT;
					sseek( &stream, streamPos );
					status = addContentListItem( &stream, envelopeInfoPtr, 
												 FALSE );
					break;

				case PGP_PACKET_SIGNATURE:
				case PGP_PACKET_SIGNATURE_ONEPASS:
					/* Try and guess whether this is a standalone signature.
					   This is rather difficult since, unlike S/MIME, there's
					   no way to tell whether a PGP signature packet is part
					   of other data or standalone.  The best we can do is
					   assume that if the caller added a hash action and we
					   find a signature, it's a detached signature.
					   Unfortunately there's no way to tell whether a
					   signature packet with no user-supplied hash is a
					   standalone signature or the start of further signed
					   data, so we can't handle detached signatures where the
					   user doesn't supply the hash */
					if( envelopeInfoPtr->usage == ACTION_SIGN && \
						envelopeInfoPtr->actionList != NULL && \
						envelopeInfoPtr->actionList->action == ACTION_HASH )
						{
						/* We can't have a detached sig packet as a one-pass
						   sig */
						if( packetType == PGP_PACKET_SIGNATURE_ONEPASS )
							{
							status = CRYPT_ERROR_BADDATA;
							break;
							}
						envelopeInfoPtr->flags |= ENVELOPE_DETACHED_SIG;
						}

					/* Read the signature/signature information packet.  We
					   allow the usage to be set already if we find a
					   signature packet since it could have been preceded by
					   a one-pass signature packet or be a detached
					   signature */
					if( envelopeInfoPtr->usage != ACTION_NONE && \
						!( packetType == PGP_PACKET_SIGNATURE && \
						   envelopeInfoPtr->usage == ACTION_SIGN ) )
						{
						status = CRYPT_ERROR_BADDATA;
						break;
						}
					envelopeInfoPtr->usage = ACTION_SIGN;
					sseek( &stream, streamPos );
					status = addContentListItem( &stream, envelopeInfoPtr,
												 FALSE );
					if( cryptStatusError( status ) )
						break;
					if( envelopeInfoPtr->flags & ENVELOPE_DETACHED_SIG )
						{
						/* If it's a one-pass sig, there's no payload
						   present, we can go straight to the postdata
						   state */
						envelopeInfoPtr->dataFlags |= ENVDATA_HASHACTIONSACTIVE;
						envelopeInfoPtr->payloadSize = 0;
						state = PGP_DEENVSTATE_DONE;
						}
					else
						state = PGP_DEENVSTATE_DATA;
					break;

				case PGP_PACKET_ENCR_MDC:
					/* The encrypted-data-with-MDC packet is preceded by a
					   version number */
					status = sgetc( &stream );
					if( !cryptStatusError( status ) && status != 1 )
						status = CRYPT_ERROR_BADDATA;
					if( cryptStatusError( status ) )
						break;
					packetLength--;
					/* Fall through */

				case PGP_PACKET_ENCR:
					if( envelopeInfoPtr->usage != ACTION_NONE && \
						envelopeInfoPtr->usage != ACTION_CRYPT )
						{
						status = CRYPT_ERROR_BADDATA;
						break;
						}

					/* Remember the packet length in case the inner packet
					   uses an indefinite-length encoding */
					if( packetLength != CRYPT_UNUSED )
						envelopeInfoPtr->payloadSize = packetLength;
					envelopeInfoPtr->usage = ACTION_CRYPT;
					state = ( packetType == PGP_PACKET_ENCR_MDC ) ? \
							PGP_DEENVSTATE_ENCR_MDC : PGP_DEENVSTATE_ENCR;
					break;

				case PGP_PACKET_MARKER:
					/* Obsolete marker packet, skip it */
					status = sSkip( &stream, packetLength );
					break;

				default:
					status = CRYPT_ERROR_BADDATA;
				}

			/* If there's a problem, exit */
			if( cryptStatusError( status ) )
				break;

			/* Remember how far we got */
			streamPos = stell( &stream );
			}

		/* Process the start of an encrypted data packet */
		if( state == PGP_DEENVSTATE_ENCR || \
			state == PGP_DEENVSTATE_ENCR_MDC )
			{
			BYTE ivInfoBuffer[ CRYPT_MAX_IVSIZE + 2 ];
			int ivSize;

			/* If there aren't any non-session-key keying resource objects
			   present, we can't go any further until we get a session key */
			if( envelopeInfoPtr->actionList == NULL )
				{
				/* There's no session key object present, add a pseudo-object
				   that takes the place of the (password-derived) session key
				   object in the content list.  This can only occur for PGP
				   2.x conventionally-encrypted data, which didn't encode any
				   algorithm information with the data, so if we get to this
				   point we know we've hit data encrypted with the default
				   IDEA/CFB derived from a user password using MD5 */
				if( envelopeInfoPtr->contentList == NULL )
					{
					status = addContentListItem( NULL, envelopeInfoPtr, FALSE );
					if( cryptStatusError( status ) )
						break;
					}

				/* We can't continue until we're given some sort of keying
				   resource */
				status = CRYPT_ENVELOPE_RESOURCE;
				break;
				}
			assert( envelopeInfoPtr->actionList->action == ACTION_CRYPT );

			/* Read and process PGP's peculiar two-stage IV */
			status = krnlSendMessage( envelopeInfoPtr->actionList->iCryptHandle,
									  IMESSAGE_GETATTRIBUTE, &ivSize, 
									  CRYPT_CTXINFO_IVSIZE );
			if( cryptStatusOK( status ) )
				status = sread( &stream, ivInfoBuffer, ivSize + 2 );
			if( !cryptStatusError( status ) )
				status = pgpProcessIV( envelopeInfoPtr->actionList->iCryptHandle,
									   ivInfoBuffer, ivSize, FALSE,
									   ( state == PGP_DEENVSTATE_ENCR ) ? \
										 TRUE : FALSE );
			if( cryptStatusError( status ) )
				break;
			envelopeInfoPtr->iCryptContext = \
								envelopeInfoPtr->actionList->iCryptHandle;

			/* If we're keeping track of the outer packet size in case
			   there's no inner size info present, adjust it by the data
			   we've just processed and any other data that may be
			   present */
			if( envelopeInfoPtr->payloadSize != CRYPT_UNUSED )
				{
				envelopeInfoPtr->payloadSize -= stell( &stream );
				if( state == PGP_DEENVSTATE_ENCR_MDC )
					/* There was a bug in all versions of GPG before 1.0.8,
					   which omitted the MDC packet length when a packet was
					   encrypted without compression.  As a result, 
					   uncompressed messages generated by this version can't
					   be processed */
					envelopeInfoPtr->payloadSize -= PGP_MDC_PACKET_SIZE;
				}

			/* If there's an MDC packet present, prepare to hash the payload
			   data */
			if( state == PGP_DEENVSTATE_ENCR_MDC )
				{
				MESSAGE_CREATEOBJECT_INFO createInfo;

				/* Append a hash action to the action list */
				setMessageCreateObjectInfo( &createInfo, CRYPT_ALGO_SHA );
				status = krnlSendMessage( SYSTEM_OBJECT_HANDLE,
										  IMESSAGE_DEV_CREATEOBJECT,
										  &createInfo, OBJECT_TYPE_CONTEXT );
				if( cryptStatusError( status ) )
					break;
				if( addAction( &envelopeInfoPtr->actionList, 
							   envelopeInfoPtr->memPoolState, ACTION_HASH,
							   createInfo.cryptHandle ) == NULL )
					{
					krnlSendNotifier( createInfo.cryptHandle,
									  IMESSAGE_DECREFCOUNT );
					status = CRYPT_ERROR_MEMORY;
					break;
					}
				envelopeInfoPtr->dataFlags |= ENVDATA_HASHACTIONSACTIVE;
				}

			/* Remember where we are and move on to the next state */
			streamPos = stell( &stream );
			state = PGP_DEENVSTATE_DATA;
			}

		/* Process the start of a data packet */
		if( state == PGP_DEENVSTATE_DATA )
			{
			/* Synchronise the data stream processing to the start of the
			   encrypted data and move back to the start of the data
			   stream */
			status = envelopeInfoPtr->syncDeenvelopeData( envelopeInfoPtr,
														  &stream );
			if( cryptStatusError( status ) )
				break;
			streamPos = 0;
			assert( actionsOK( envelopeInfoPtr ) );

			/* Move on to the next state.  For plain data we're done,
			   however for other content types we have to either process or
			   strip out the junk PGP puts at the start of the content */
			if( envelopeInfoPtr->usage != ACTION_NONE )
				{
				envelopeInfoPtr->oobEventCount = 1;
				state = PGP_DEENVSTATE_DATA_HEADER;
				}
			else
				state = PGP_DEENVSTATE_DONE;
			assert( actionsOK( envelopeInfoPtr ) );
			}

		/* PGP doesn't provide any indication of what the content of the
		   current packet is, so we have to burrow down into the encrypted
		   data to see whether the payload needs any further processing.
		   This state looks ahead into this data to see whether we need to
		   strip the header (for a plain data packet) or inform the user
		   that there's a nested content type */
		if( state == PGP_DEENVSTATE_DATA_HEADER )
			{
			STREAM headerStream;
			BYTE buffer[ 64 + 256 ];
			int bytesWanted;

			/* If there's no out-of-band data left to remove at the start of
			   the payload, we're done */
			if( !envelopeInfoPtr->oobEventCount && \
				!envelopeInfoPtr->oobDataLeft )
				break;

			/* We have to perform all sorts of special-case processing to
			   handle the out-of-band packet header at the start of the
			   payload.  Initially, we need to find out how much header data
			   is actually present.  The header consists of:
				byte	ctb
				byte[]	length
				byte	type = 'b' | 't'
				byte	filename length
				byte[]	filename
				byte[4]	timestamp

			   The smallest size for this header (1-byte length, no filename)
			   is 1 + 1 + 1 + 1 + 4 = 8 bytes.  This is also just enough to
			   get us to the filename length for a maximum-size header, which
			   is 1 + 5 + 1 + 1 bytes up to the filename length.  Thus we
			   read 8 bytes */
			bytesWanted = envelopeInfoPtr->oobEventCount ? \
						  -8 : envelopeInfoPtr->oobDataLeft;

			/* Try and read the the requested amount of out-of-band data
			   from the start of the payload */
			length = envelopeInfoPtr->copyFromEnvelopeFunction( envelopeInfoPtr,
														buffer, bytesWanted );
			if( cryptStatusError( length ) )
				status = length;
			else
				if( length < \
					( ( bytesWanted >= 0 ) ? bytesWanted : -bytesWanted ) )
					status = CRYPT_ERROR_UNDERFLOW;
			if( cryptStatusError( status ) )
				break;

⌨️ 快捷键说明

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