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

📄 pgpkeyio.c

📁 可以实现对邮件的加密解密以及签名
💻 C
📖 第 1 页 / 共 4 页
字号:
									   IsntNull(*db)?&db2:db );
			if( IsPGPError( err ) )
				goto error;

			if( IsNull( *db ) )
			{
				err = kPGPError_X509NeededCertNotAvailable;
				goto error;
			}

			/* Combine keysets if necessary */
			if( IsntNull( db2 ) )
			{
				PGPKeySetRef crls;
				err = PGPCopyKeys( pgpKeyDBPeekRootSet(db2), *db, &crls );
				if( IsPGPError( err ) )
					goto error;
				PGPFreeKeyDB( db2 );
				db2 = NULL;
				/* Run a sig check to make CRL effective */
				PGPCheckKeyRingSigs( crls, NULL, FALSE, NULL, NULL );
			}
			else
			{
				/* Run a sig check to make CRL effective */
				PGPCheckKeyRingSigs( pgpKeyDBPeekRootSet(*db), NULL,
									 FALSE, NULL, NULL );
			}
		}
	}

error:
	if( mustFreeBuf )
		PGPFreeData( bufPtr );
	if( IsntNull( certSet ) )
		PGPFreeData( certSet );
	if( IsntNull( crlSet ) )
		PGPFreeData( crlSet );
	if( IsntNull( db2 ) )
		PGPFreeKeyDB( db2 );

	return err;
}



static const PGPOptionType impkeyOptionSet[] = {
	kPGPOptionType_InputFileRef,
	kPGPOptionType_LocalEncoding,
	kPGPOptionType_InputBuffer,
	kPGPOptionType_EventHandler,
	kPGPOptionType_SendNullEvents,
	kPGPOptionType_InputFormat,
	kPGPOptionType_Passphrase,
	kPGPOptionType_CachePassphrase,
	kPGPOptionType_X509Encoding,
	kPGPOptionType_KeyDBRef
};

/* Frees optionList, unlike most other internal functions */
	PGPError
pgpImportKeySetInternal (PGPContextRef context, PGPKeyDBRef *keydb,
	PGPOptionListRef optionList)
{
	PGPError		err = kPGPError_NoErr;
	PGPKeyDBRef		kdb;
	PGPInputFormat	inputFormat;
	PGPUInt32		fDo509;

	if (IsPGPError( err = pgpCheckOptionsInSet( optionList,
						impkeyOptionSet, elemsof( impkeyOptionSet ) ) ) )
		return err;

	pgpAssertAddrValid( keydb, PGPKeyDBRef );
	*keydb = NULL;
	
	if( IsPGPError( err = pgpFindOptionArgs( optionList,
						 kPGPOptionType_X509Encoding, FALSE,
						 "%d", &fDo509 ) ) )
		goto error;

	if( IsPGPError( err = pgpFindOptionArgs( optionList,
						 kPGPOptionType_InputFormat, FALSE,
						 "%d", &inputFormat ) ) )
		goto error;

	if( fDo509 || inputFormat >= kPGPInputFormat_X509DataInPKCS7 )
	{
		err = sImportX509Certificate( context, keydb, inputFormat, optionList);
		PGPFreeOptionList( optionList );
		goto error;
	}

	if( IsPGPError( err = PGPNewKeyDB( context, &kdb ) ) )
		goto error;

	if( IsPGPError( err = PGPDecode( context, optionList,
									 PGPODiscardOutput(context, TRUE),
									 PGPOImportKeysTo(context, kdb),
									 PGPOLastOption(context) ) ) ) {
		PGPFreeKeyDB( kdb );
		goto error;
	}
	*keydb = kdb;
	
error:
	return err;
}


/*
 * Add our custom PGP X.509 extension, if useExtension is true.  Else add
 * the data to the description field.  Fill into *av.  buf is a working
 * buff at least 40 bytes long.  key tells which key to get the PGP data
 * from.
 */
	static void
sAddPGPX509Extension( PGPAttributeValue *av, char *buf, PGPKeyDBObjRef key,
					  PGPBoolean useExtension )
{
	static char			 s_pgpkeycr[] = "PGPKeyCreation=0x";
	static PGPByte		 s_pgpx509keycr [] = {
		0x30, 0x0e,		/* SEQUENCE */
			/* PGP Extension OID */
			/* (1 3 6 1 4 1 3401 8 1 1) */
			0x06, 0x0a, 0x2b, 0x06, 0x01, 0x04, 0x01, 0x9a, 0x49, 0x08,
					0x01, 0x01,
			0x04, 0x00	/* Octet string */
			/* Value as UTCTime value goes here */
	};

	if( useExtension )
	{
		/* Use a new extension */
		PGPUInt32 kcr = pgpKeyCreation (key);
		PGPByte *px = (PGPByte *)buf + sizeof(s_pgpx509keycr);
		PGPSize tlen;
		char tbuf[PGPX509TIMELEN+1];

		tlen = pgpTimeToX509Time( kcr, tbuf );
		pgpCopyMemory( s_pgpx509keycr, buf, sizeof(s_pgpx509keycr) );
		buf[1] += tlen + 2;
		buf[sizeof(s_pgpx509keycr)-1] += tlen + 2;
		/* Choose GeneralizedTime vs UTCTime tag */
		*px++ = (tlen == PGPX509TIMELEN) ? 24 : 23;
		*px++ =  tlen;
		pgpCopyMemory( tbuf, px, tlen );
		av->attribute = kPGPAVAttribute_CertificateExtension;
		av->size = sizeof(s_pgpx509keycr) + 2 + tlen;
		av->value.pointervalue = buf;
		av->unused = 0;
	}
	else
	{
		/* Use description field in subject name */
		pgpCopyMemory( s_pgpkeycr, buf, sizeof(s_pgpkeycr)-1 );
		sprintf ( buf+sizeof(s_pgpkeycr)-1, "%08x",
				  pgpKeyCreation (key) );
		av->attribute = kPGPAVAttribute_Description;
		av->size = sizeof(s_pgpkeycr)-1 + 8;
		av->value.pointervalue = buf;
		av->unused = 0;
	}
}



/*
 * Handle X509 based export formats.
 * Key is the top level key we are exporting; keyset controls which
 * sub objects if any we should look at
 */
static PGPError
sExportKeyX509 (
	PGPKeyDBObjRef	 	key,
	PGPKeySetRef		keyset,
	PGPExportFormat		exportFormat,
	PGPOptionListRef	optionList
	)
{
	PGPContextRef		context;
	PGPKeyDBRef			kdb;
	PGPError			err = kPGPError_NoErr;
	PGPByte				*buf = NULL;
	PGPSize				 bufLength = 0;
	PGPBoolean			 freeBuf = FALSE;
	PGPUInt32			 fExportSecrets;
	PGPMemoryMgrRef		 mgr;
	void				*vFormatData;
	PGPAttributeValue	*formatData;
	PGPAttributeValue	*formatDataCopy = NULL;
	PGPAttributeValue	*newAV;
	PGPSize				 formatDataLength;
	PGPOptionListRef	 passphrase = NULL;
	PGPByte				*dpoint = NULL;
	PGPSize				 dpointlen = 0;
	PGPInt32			 annotate = 0;
	char				 pgpkeycr[40];	/* big enough for either case */

	kdb = PGPPeekKeyDBObjKeyDB( key );
	context = PGPPeekKeyDBContext( kdb );
	mgr = PGPPeekContextMemoryMgr( context );

	if (exportFormat == kPGPExportFormat_X509Cert) {
		/* Find the right X509 sig, somehow */
		PGPKeyDBObj *obj = NULL;
		PGPKeyDBObj *bestsig = NULL;
		PGPKeyIter *iter;

		if( IsPGPError( err = PGPNewKeyIterFromKeySet( keyset, &iter ) ) )
			goto error;
		while( IsntPGPError( pgpKeyIterNextObject( iter, &obj ) ) ) {
			if (pgpObjectType(obj) == RINGTYPE_SIG &&
				pgpSigIsX509 (obj)) {
				PGPKeyDBObj *signer = pgpSigMaker (obj);
				/* Use a self-sig if exists, else use first sig */
				if (signer == obj->up) {
					bestsig = obj;
				} else if (bestsig == NULL) {
					bestsig = obj;
				}
			}
		}
		PGPFreeKeyIter( iter );
		iter = NULL;
		if (bestsig != NULL) {
			buf = pgpSigX509Certificate( bestsig, &bufLength );
		}
		annotate = PGPANN_ARMORX509_CERTIFICATE;
		if( IsPGPError( err = pgpFindOptionArgs( optionList,
							 kPGPOptionType_ExportPrivateKeys, FALSE,
							 "%d", &fExportSecrets ) ) )
			goto error;
		if( fExportSecrets )
		{
			/* Do PKCS-12 conversion */
			PGPByte *password;
			PGPSize passwordLength;
			PGPByte *p8buf;
			PGPSize p8buflen;
			PGPByte *p12buf;
			PGPSize p12buflen;
			PGPByte *friendlyName;
			PGPSize friendlyLen;
			PGPSecKey *seckey;
			PGPKeyDBObjRef userID;

			if( IsPGPError( err = pgpFindOptionArgs( optionList,
								kPGPOptionType_Passphrase, FALSE,
								"%p%l", &password, &passwordLength ) ) )
				goto error;

			seckey = pgpSecSecKey (key, PGP_PKUSE_SIGN);
			if (!seckey)
			{
				err = pgpKeyDBError(PGPPeekKeyDBObjKeyDB(key));
				goto error;
			}
			err = pgpSecKeyUnlock( seckey, (char *) password, passwordLength, FALSE );
			if( err != 1 )
			{
				err = kPGPError_BadPassphrase;
				goto error;
			}
			err = pgpEncodePKCS8( seckey, &p8buf, &p8buflen );
			pgpSecKeyDestroy( seckey );
			if( IsPGPError( err ) )
				goto error;
			PGPGetPrimaryUserID( key, &userID );
			pgpGetUserIDAllocatedStringBuffer( userID, kPGPUserIDProperty_Name,
											   &friendlyName, &friendlyLen );
			err = pgpCreateCertSetFromChain( context, bestsig, &buf,
											 &bufLength );
			if( IsPGPError( err ) )
			{
				PGPFreeData( friendlyName );
				PGPFreeData( p8buf );
				goto error;
			}
			err = PKCS12ExportKey( context, p8buf, p8buflen, password,
								   passwordLength, buf, bufLength,
								   friendlyName, friendlyLen,
								   1, 1000, kPGPPBEAlgorithm_SHA3DES,
								   &p12buf, &p12buflen );
			PGPFreeData( buf );
			PGPFreeData( p8buf );
			PGPFreeData( friendlyName );
			if( IsPGPError( err ) )
				goto error;
			buf = p12buf;
			bufLength = p12buflen;
			freeBuf = TRUE;
			annotate = PGPANN_ARMORX509_PRIVATE;
		}
	} else if (exportFormat >= kPGPExportFormat_X509GetCRL) {
		time_t curtime = PGPGetStdTimeFromPGPTime( PGPGetTime() );

		/* If InputBuffer is specified, it is CRL distribution point */
		if( IsPGPError( err = pgpFindOptionArgs( optionList,
							 kPGPOptionType_InputBuffer, FALSE,
							 "%p%l", &dpoint, &dpointlen ) ) )
			goto error;

		err = X509CreateCRLRequest ( context, key, dpoint, dpointlen,
				exportFormat, curtime, &buf, &bufLength );
		if( IsPGPError( err ) )
			goto error;

		freeBuf = TRUE;
	} else if (exportFormat >= kPGPExportFormat_X509GetCertInitial) {
		/* Structure for now will be a fixed empty sequence */
		static PGPByte emptysequence[] = {0x30, 0x00};
		buf = emptysequence;
		bufLength = sizeof(emptysequence);
		freeBuf = FALSE;
	} else if (exportFormat >= kPGPExportFormat_X509CertReq) {
		PGPOption passop;

		if( IsPGPError( err = pgpSearchOptionSingle( optionList,
									kPGPOptionType_Passphrase, &passop ) ) )
			goto error;
		if( IsntOp( passop ) ) {
			if( IsPGPError( err = pgpSearchOptionSingle( optionList,
										kPGPOptionType_Passkey, &passop ) ) )
				goto error;
		}

		if( IsOp( passop ) ) {
			PGPOption passopcopy;
			pgpCopyOption( context, &passop, &passopcopy );
			passphrase = pgpNewOneOptionList( context, &passopcopy );
		}

		if( IsPGPError( err = pgpFindOptionArgs( optionList,
							 kPGPOptionType_AttributeValue, FALSE,
							 "%p%l",
							 &vFormatData, &formatDataLength ) ) )
			goto error;
		formatData = vFormatData;
		formatDataLength /= sizeof(PGPAttributeValue);
		formatDataCopy = PGPNewData( mgr,
					(formatDataLength+1)*sizeof(PGPAttributeValue), 0 );
		if( IsNull( formatDataCopy ) ) {
			err = kPGPError_OutOfMemory;
			goto error;
		}
		pgpCopyMemory( formatData, formatDataCopy+1,
					   formatDataLength*sizeof(PGPAttributeValue) );
		newAV = formatDataCopy;

		/* Add "description" or extension field to hold keycreation data */
		sAddPGPX509Extension( newAV, pgpkeycr, key,
		  (PGPBoolean)(exportFormat==kPGPExportFormat_VerisignV1_CertReq ) );

		err = X509CreateCertificateRequest ( context, key, exportFormat,
				formatDataCopy, formatDataLength+1, passphrase,
				&buf, &bufLength );
		passphrase = NULL;
		PGPFreeData( formatDataCopy );
		formatDataCopy = NULL;
		if( IsPGPError( err ) )
			goto error;

		freeBuf = TRUE;
		annotate = PGPANN_ARMORX509_CERT_REQUEST;
	} else {
		pgpAssert (0);
	}

	err = pgpOutputBufferByOptionList( context, buf, bufLength, optionList, annotate );

error:

	if( IsntNull( passphrase ) )
		pgpFreeOptionList( passphrase );
	if( IsntNull( formatDataCopy ) )
		PGPFreeData( formatDataCopy );
	if( freeBuf && IsntNull( buf ) )
		PGPFreeData( buf );

	return err;
}


static const PGPOptionType cx509OptionSet[] = {
	kPGPOptionType_Passphrase,
	kPGPOptionType_Passkey,
	kPGPOptionType_CachePassphrase,
	kPGPOptionType_InputFileRef,
	kPGPOptionType_LocalEncoding,
	kPGPOptionType_InputBuffer,
	kPGPOptionType_AttributeValue,
	kPGPOptionType_Expiration,
	kPGPOptionType_CreationDate

};


/*
 * Create X.509 certificate.  If targetkey is NULL use PKCS-10 request
 * from PGPOInput options instead.
 */
	PGPError
pgpCreateX509CertificateInternal(
	PGPKeyDBObjRef		signer,
	PGPKeyDBObjRef	 	targetkey,
	PGPKeyDBObjRef		*sig,
	PGPOptionListRef	optionList
	)
{
	PGPContextRef		context;
	PGPMemoryMgrRef		mgr;
	char *				passphrase;
	PGPSize				passphraseLength;
	PGPBoolean			hashedPhrase = FALSE;
	PGPTime				creationTime;
	PGPUInt32			expirationDays;
	PGPError			err;
	void				*vFormatData;
	PGPAttributeValue	*formatData;
	PGPAttributeValue	*formatDataCopy = NULL;
	PGPSize				formatDataLength;
	PGPByte				*pkcs10Buffer = NULL;
	PGPSize				pkcs10BufferSize;
	PGPBoolean			mustFreeBuf = FALSE;
	char				 pgpkeycr[40];	/* big enough for custom ext. */

	if (IsPGPError( err = pgpCheckOptionsInSet( optionList,
						cx509OptionSet, elemsof( cx509OptionSet ) ) ) )
		return err;

	context = PGPPeekKeyDBObjContext( signer );

⌨️ 快捷键说明

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