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

📄 pgp_env.c

📁 提供了很多种加密算法和CA认证及相关服务如CMP、OCSP等的开发
💻 C
📖 第 1 页 / 共 3 页
字号:
/****************************************************************************
*																			*
*					 cryptlib PGP Enveloping Routines						*
*					 Copyright Peter Gutmann 1996-2002						*
*																			*
****************************************************************************/

#include <stdlib.h>
#include <string.h>
#include <time.h>
#if defined( INC_ALL )
  #include "envelope.h"
  #include "pgp.h"
#elif defined( INC_CHILD )
  #include "../envelope/envelope.h"
  #include "../envelope/pgp.h"
#else
  #include "envelope/envelope.h"
  #include "envelope/pgp.h"
#endif /* Compiler-specific includes */

/* Prototypes for functions in envelope.c */

int copyFromAuxBuffer( ENVELOPE_INFO *envelopeInfoPtr );
int copyFromAuxStream( ENVELOPE_INFO *envelopeInfoPtr );

/****************************************************************************
*																			*
*								Utility Routines							*
*																			*
****************************************************************************/

/* Check that a requested algorithm type is valid with PGP data */

static int checkCryptAlgo( const CRYPT_ALGO cryptAlgo, 
						   const CRYPT_ALGO cryptMode )
	{
	return( ( isPGPCryptAlgo( cryptAlgo ) && cryptMode == CRYPT_MODE_CFB ) ? \
			CRYPT_OK : CRYPT_ERROR_NOTAVAIL );
	}

static int checkHashAlgo( const CRYPT_ALGO hashAlgo )
	{
	return( isPGPHashAlgo( hashAlgo ) ? CRYPT_OK : CRYPT_ERROR_NOTAVAIL );
	}

/****************************************************************************
*																			*
*						Write Key Exchange/Signature Packets				*
*																			*
****************************************************************************/

/* Write a PGP packet header */

static int writePacketHeader( STREAM *stream, const int packetType,
							  const long length )
	{
#if 0	/* PGP 2.x */
	/* Write the CTB and length */
	if( length <= 0xFF )
		{
		sputc( stream, PGP_CTB | ( packetType << 2 ) );
		return( sputc( stream, length ) );
		}
	if( length <= 0xFFFF )
		{
		sputc( stream, PGP_CTB | ( packetType << 2 ) | 0x01 );
		sputc( stream, ( length >> 8 ) & 0xFF );
		return( sputc( stream, ( length & 0xFF ) ) );
		}
	sputc( stream, PGP_CTB | ( packetType << 2 ) | 0x02 );
	sputc( stream, ( length >> 24 ) & 0xFF );
	sputc( stream, ( length >> 16 ) & 0xFF );
	sputc( stream, ( length >> 8 ) & 0xFF );
	return( sputc( stream, ( length & 0xFF ) ) );
#else	/* OpenPGP */
	if( packetType == PGP_PACKET_COPR )
		/* Compressed data packets use a special unkown-length encoding
		   which doesn't work like any other PGP packet type */
		return( sputc( stream, PGP_CTB_COMPRESSED ) );
	if( packetType )
		sputc( stream, PGP_CTB_OPENPGP | packetType );
	if( length <= 191 )
		return( sputc( stream, length ) );
	if( length <= 8383 )
		{
		sputc( stream, ( ( length >> 8 ) & 0xFF ) + 192 );
		return( sputc( stream, ( length & 0xFF ) ) );
		}
	sputc( stream, 0xFF );
	sputc( stream, ( length >> 24 ) & 0xFF );
	sputc( stream, ( length >> 16 ) & 0xFF );
	sputc( stream, ( length >> 8 ) & 0xFF );
	return( sputc( stream, ( length & 0xFF ) ) );
#endif /* 0 */
	}

static int sizeofPacketHeader( const long length )
	{
#if 0	/* PGP 2.x */
	return( ( length <= 0xFF ) ? 2 : ( length <= 0xFFFF ) ? 3 : 5 );
#else	/* OpenPGP */
	return( ( length <= 191 ) ? 2 : ( length <= 8383 ) ? 3 : 5 );
#endif /* 0 */
	}

/* Write various cryptlib algorithm types as PGP algorithm IDs */

static int writeHashAlgorithmID( STREAM *stream, const CRYPT_ALGO cryptAlgo )
	{
	switch( cryptAlgo )
		{
		case CRYPT_ALGO_MD2:
			return( sputc( stream, PGP_ALGO_MD2 ) );

		case CRYPT_ALGO_MD5:
			return( sputc( stream, PGP_ALGO_MD5 ) );

		case CRYPT_ALGO_SHA:
			return( sputc( stream, PGP_ALGO_SHA ) );

		case CRYPT_ALGO_RIPEMD160:
			return( sputc( stream, PGP_ALGO_RIPEMD160 ) );
		}

	assert( NOTREACHED );
	return( CRYPT_ERROR );	/* Get rid of compiler warning */
	}

static int writeCryptAlgorithmID( STREAM *stream, 
								  const CRYPT_ALGO cryptAlgo )
	{
	switch( cryptAlgo )
		{
		case CRYPT_ALGO_3DES:
			return( sputc( stream, PGP_ALGO_3DES ) );

		case CRYPT_ALGO_AES:
			return( sputc( stream, PGP_ALGO_AES_128 ) );

		case CRYPT_ALGO_BLOWFISH:
			return( sputc( stream, PGP_ALGO_BLOWFISH ) );

		case CRYPT_ALGO_CAST:
			return( sputc( stream, PGP_ALGO_CAST5 ) );

		case CRYPT_ALGO_IDEA:
			return( sputc( stream, PGP_ALGO_IDEA ) );
		}

	assert( NOTREACHED );
	return( CRYPT_ERROR );	/* Get rid of compiler warning */
	}

/* Write various PGP packets.

   SKE:	byte	version = 4
		byte	cryptAlgo
		byte	stringToKey specifier
		byte[]	stringToKey data */

static int writeSKEPacket( STREAM *stream, const CRYPT_CONTEXT iCryptContext )
	{
	CRYPT_ALGO hashAlgo, cryptAlgo;
	BYTE salt[ CRYPT_MAX_HASHSIZE ];
	int keySetupIterations, count = 0, status;

	/* Get the key derivation information */
	status = krnlSendMessage( iCryptContext, 
						RESOURCE_IMESSAGE_GETATTRIBUTE, 
						&keySetupIterations, CRYPT_CTXINFO_KEYING_ITERATIONS );
	if( cryptStatusOK( status ) )
		status = krnlSendMessage( iCryptContext, 
						RESOURCE_IMESSAGE_GETATTRIBUTE, 
						&hashAlgo, CRYPT_CTXINFO_KEYING_ALGO );
	if( cryptStatusOK( status ) )
		status = krnlSendMessage( iCryptContext, 
						RESOURCE_IMESSAGE_GETATTRIBUTE, 
						&cryptAlgo, CRYPT_CTXINFO_ALGO );
	if( cryptStatusOK( status ) )
		{
		RESOURCE_DATA msgData;

		setResourceData( &msgData, salt, CRYPT_MAX_HASHSIZE );
		status = krnlSendMessage( iCryptContext, 
						RESOURCE_IMESSAGE_GETATTRIBUTE_S, 
						&msgData, CRYPT_CTXINFO_KEYING_SALT );
		}
	if( cryptStatusError( status ) )
		return( status );

	/* Calculate the PGP "iteration count" from the value used to derive
	   the key.  The "iteration count" is actually a count of how many bytes 
	   are hashed, this is because the "iterated hashing" treats the salt + 
	   password as an infinitely-repeated sequence of values and hashes the 
	   resulting string for PGP-iteration-count bytes worth.  Instead of 
	   being written directly the count is encoded in a complex manner which
	   saves a whole byte, so before we can write it we have to encode it 
	   into the base + exponent form expected by PGP.  This has a default 
	   base of 16 + the user-supplied base value, we can set this to zero
	   since the iteration count used by cryptlib is always a multiple of
	   16, the remainder is just log2 of what's left of the iteration 
	   count */
	assert( keySetupIterations % 16 == 0 );
	keySetupIterations /= 32;	/* Remove fixed offset before log2 op.*/
	while( keySetupIterations )
		{
		count++;
		keySetupIterations >>= 1;
		}
	count <<= 4;				/* Exponent comes first */

	/* Write the SKE packet */
	writePacketHeader( stream, PGP_PACKET_SKE, 4 + PGP_SALTSIZE + 1 );
	sputc( stream, 4 );		/* Version = 4 (OpenPGP) */
	writeCryptAlgorithmID( stream, cryptAlgo );
	sputc( stream, 3 );		/* S2K = salted, iterated hash */
	writeHashAlgorithmID( stream, hashAlgo );
	swrite( stream, salt, PGP_SALTSIZE );
	return( sputc( stream, count ) );
	}

/* PKE:	byte	version = 2 or 3
		byte[8]	keyID
		byte	PKC algo
		mpi(s)	encrypted session key */

static int writePKEPacket( STREAM *stream, 
						   const CRYPT_CONTEXT iSessionKeyContext,
						   const CRYPT_CONTEXT iExportContext )
	{
	CRYPT_ALGO cryptAlgo;
	MECHANISM_WRAP_INFO mechanismInfo;
	BYTE buffer[ ( CRYPT_MAX_PKCSIZE * 2 ) + 64 ], *bufPtr = buffer;
	BYTE keyID[ PGP_KEYID_SIZE ];
	int bufSize = CRYPT_MAX_PKCSIZE, wrappedKeySize, status;

	/* Get the key information */
	status = krnlSendMessage( iExportContext, 
							  RESOURCE_IMESSAGE_GETATTRIBUTE, 
							  &cryptAlgo, CRYPT_CTXINFO_ALGO );
	if( cryptStatusOK( status ) )
		{
		RESOURCE_DATA msgData;

		setResourceData( &msgData, keyID, PGP_KEYID_SIZE );
		status = krnlSendMessage( iExportContext, 
								  RESOURCE_IMESSAGE_GETATTRIBUTE_S, 
								  &msgData, CRYPT_IATTRIBUTE_OPENPGP_KEYID );
		}
	if( cryptStatusError( status ) )
		return( status );

	/* Wrap the key using PGP's variant of PKCS #1 */
	if( sIsNullStream( stream ) )
		{
		bufPtr = NULL;
		bufSize = 0;
		}
	setMechanismWrapInfo( &mechanismInfo, bufPtr, bufSize, NULL, 0, 
						  iSessionKeyContext, iExportContext, CRYPT_UNUSED );
	status = krnlSendMessage( iExportContext, RESOURCE_IMESSAGE_DEV_EXPORT, 
							  &mechanismInfo, MECHANISM_PKCS1_PGP );
	wrappedKeySize = mechanismInfo.wrappedDataLength;
	clearMechanismInfo( &mechanismInfo );
	if( cryptStatusError( status ) )
		return( status );

	/* Write the PKE packet */
	if( cryptAlgo == CRYPT_ALGO_RSA )
		{
		writePacketHeader( stream, PGP_PACKET_PKE, 
						   1 + PGP_KEYID_SIZE + 1 + \
								sizeofMPI( wrappedKeySize ) );
		sputc( stream, 3 );		/* Version = 3 (OpenPGP) */
		swrite( stream, keyID, PGP_KEYID_SIZE );
		sputc( stream, PGP_ALGO_RSA );
		status = pgpWriteMPI( stream, buffer, wrappedKeySize );
		}
	else
		{
		assert( cryptAlgo == CRYPT_ALGO_ELGAMAL );
		writePacketHeader( stream, PGP_PACKET_PKE, 
						   1 + PGP_KEYID_SIZE + 1 + wrappedKeySize );
		sputc( stream, 3 );		/* Version = 3 (OpenPGP) */
		swrite( stream, keyID, PGP_KEYID_SIZE );
		sputc( stream, PGP_ALGO_ELGAMAL );
		status = swrite( stream, buffer, wrappedKeySize );
		}
	zeroise( buffer, CRYPT_MAX_PKCSIZE );

	return( status );
	}

/* Signature info:
		byte	version = 3
		byte	sigType
		byte	hashAlgo
		byte	sigAlgo
		byte[8]	keyID
		byte	1 */

static int writeSignatureInfoPacket( STREAM *stream, 
									 const CRYPT_CONTEXT iSignContext,
									 const CRYPT_CONTEXT iHashContext )
	{
	CRYPT_ALGO hashAlgo, signAlgo;
	BYTE keyID[ PGP_KEYID_SIZE ];
	int status;

	/* Get the signature information */
	status = krnlSendMessage( iHashContext, 
							  RESOURCE_IMESSAGE_GETATTRIBUTE, 
							  &hashAlgo, CRYPT_CTXINFO_ALGO );
	if( cryptStatusOK( status ) )
		status = krnlSendMessage( iSignContext, 
								  RESOURCE_IMESSAGE_GETATTRIBUTE, 
								  &signAlgo, CRYPT_CTXINFO_ALGO );
	if( cryptStatusOK( status ) )
		{
		RESOURCE_DATA msgData;

		setResourceData( &msgData, keyID, PGP_KEYID_SIZE );
		status = krnlSendMessage( iSignContext, 
								  RESOURCE_IMESSAGE_GETATTRIBUTE_S, 
								  &msgData, CRYPT_IATTRIBUTE_OPENPGP_KEYID );
		}
	if( cryptStatusError( status ) )
		return( status );

	/* Write the signature info packet */
	writePacketHeader( stream, PGP_PACKET_SIGNATURE_ONEPASS, 
					   1 + 1 + 1 + 1 + PGP_KEYID_SIZE + 1 );
	sputc( stream, 3 );		/* Version = 3 (OpenPGP) */
	sputc( stream, 0 );		/* Binary document sig. */
	writeHashAlgorithmID( stream, hashAlgo );
	sputc( stream, ( signAlgo == CRYPT_ALGO_RSA ) ? \
		   PGP_ALGO_RSA : PGP_ALGO_DSA );
	swrite( stream, keyID, PGP_KEYID_SIZE );
	return( sputc( stream, 1 ) );
	}

/* Signature:
		byte	version = 4

⌨️ 快捷键说明

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