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

📄 pgpkeyadd.c

📁 可以实现对邮件的加密解密以及签名
💻 C
📖 第 1 页 / 共 5 页
字号:
		default:
			pgpAssert(0);
		case RINGTYPE_KEY:
		case RINGTYPE_SUBKEY:
			pgpAssert(OBJISKEY(newobj));
			okinfo = pgpKeyToKeyInfo( oldobj );
			nkinfo = pgpKeyToKeyInfo( newobj );
			nkinfo->trust = pgpMax(okinfo->trust, nkinfo->trust);
			nkinfo->validityperiod = pgpMax(okinfo->validityperiod,
											nkinfo->validityperiod);
			/* Copy residence on crypto token */
			if( okinfo->flags & KEYF_TOKEN )  {
				nkinfo->flags |= KEYF_TOKEN;
				nkinfo->tokenNum1 = okinfo->tokenNum1;
                        }
			break;
		case RINGTYPE_SIG:
			pgpAssert(OBJISSIG(newobj));
			osinfo = pgpSigToSigInfo( oldobj );
			nsinfo = pgpSigToSigInfo( newobj );
			if( (osinfo->trust & PGP_SIGTRUSTF_CHECKED) &&
				!(nsinfo->trust & PGP_SIGTRUSTF_CHECKED) )
			{
				/* Newly trusted signature */
				if( SIGISPRIMARYUID (nsinfo) )
				{
					/* Clear any manual primary uid settings we had */
					PGPKeyDBObjRef key = PGPPeekKeyDBObjKey( newobj );
					if( pgpSigMaker( newobj ) == key )
						pgpKeyClearPrimaryUserIDs( key, (PGPUInt32)-1UL );
				}
			}
			nsinfo->trust = pgpMax(osinfo->trust, nsinfo->trust);
			break;
		case RINGTYPE_CRL:
			pgpAssert(OBJISCRL(newobj));
			ocinfo = pgpCRLToCRLInfo( oldobj );
			ncinfo = pgpCRLToCRLInfo( newobj );
			ncinfo->trust = pgpMax(ocinfo->trust, ncinfo->trust);
			break;
		case RINGTYPE_UNK:
			pgpAssert(pgpObjectType(newobj) == RINGTYPE_UNK);
			oninfo = pgpUnkToUnkInfo( oldobj );
			nninfo = pgpUnkToUnkInfo( newobj );
			nninfo->trust = pgpMax(oninfo->trust, nninfo->trust);
			break;
		}
	}
}


static PGPError
sCleanupThirdPartyRevocations(PGPKeyDBObj *key, PGPBoolean trusted)
{
	PGPKeyDBObj *rsig, *nextrsig;
	PGPKeyDBObj *ssig;
	PGPSigInfo *rsinfo, *ssinfo;
	PGPKeyInfo *rskinfo;
	PGPBoolean success;
	PGPUInt32 i;
	PGPUInt32 matches;
	PGPByte const *p;
	PGPSize len;

	(void) trusted;
	for( rsig=key->down; IsntNull(rsig); rsig=nextrsig )
	{
		nextrsig = rsig->next;
		if( !OBJISSIG(rsig) )
			continue;
		rsinfo = pgpSigToSigInfo( rsig );
		if( rsinfo->type != PGP_SIGTYPE_KEY_REVOKE )
			continue;
		if( rsinfo->by == key )
			continue;
		rskinfo = pgpKeyToKeyInfo( rsinfo->by );
		/* Here we have a third party revocation signature */
		/* See if there is a self-sig on the key that authorizes it */
		success = FALSE;
		for( ssig=key->down; IsntNull(ssig); ssig=ssig->next )
		{
			if( !OBJISSIG(ssig) )
				continue;
			ssinfo = pgpSigToSigInfo( ssig );
			if( ssinfo->type != PGP_SIGTYPE_KEY_PROPERTY )
				continue;
			if( ssinfo->by != key )
				continue;
			p = pgpFetchObject( ssig, &len );
			if( IsNull(p) )
				continue;
			i = 0;
			do {
				PGPBoolean hashed;
				p = pgpSigFindSubpacket( p,
								SIGSUB_KEY_REVOCATION_KEY, i++, NULL, NULL,
								&hashed, NULL, &matches );
				if( !p  || !hashed )
					break;
				/*
				 * data is 1 byte of class, 1 of pkalg, 20 bytes of
				 * fingerprint.  Last 8 of 20 are keyid.
				 */
				if( pgpMemoryEqual( p+2+20-8, rskinfo->keyID, 8 ) &&
							p[1] == rskinfo->pkalg )
				{
					/* Test to see that the self-sig is valid */
					if( !pgpSigTried( ssig ) )
					{
						/* Validate the self-sig */
						PGPKeySetRef kset;
						PGPNewOneKeySet( ssig, &kset );
						if( IsntNull( kset ) )
						{
							pgpCheckKeySigs( kset, NULL, FALSE, FALSE, FALSE,
											 NULL, NULL, NULL );
							PGPFreeKeySet( kset );
						}
					}
					/* Only accept if self-sig is valid */
					if( pgpSigChecked( ssig ) )
						success = TRUE;
					/* No point in searching ssig further even if bad */
					break; /* out of while( i<matches) loop */
				}
			} while( i < matches  &&  !success );
			if( success )
				break;
		}
		/* Now verify revocation sig if we can */
		if( success )
		{
			/* Look for signing key in any keydb */
			PGPKeyDBObjRef signkey = NULL;
			PGPContextRef context = PGPPeekKeyDBObjContext( key );
			PGPKeyDBRef refdb = pgpContextGetFirstKeyDB(context);
			PGPKeyID keyid;

			pgpSigID8( rsig, NULL, &keyid );
			while( IsntNull( refdb )  &&  IsNull( signkey ) )
			{
				pgpGetKeyByKeyID( refdb, &keyid, FALSE, FALSE, &signkey );
				if( IsNull(signkey) )
					refdb = pgpKeyDBNextKeyDB( refdb );
			}
			if( IsntNull( signkey ) )
			{
				/* If found signkey, verify rev signature and remove if bad */
				pgpAssert( pgpKeyDBObjIsReal( signkey ) );
				if( !pgpSigTried( rsig ) )
				{
					/* Validate the revocation sig */
					PGPKeySetRef kset;
					PGPNewOneKeySet( rsig, &kset );
					if( IsntNull( kset ) )
					{
						if( refdb == PGPPeekKeySetKeyDB( kset ) )
							refdb = NULL;
						pgpCheckKeySigs( kset, refdb, FALSE, FALSE, FALSE,
										 NULL, NULL, NULL );
						PGPFreeKeySet( kset );
					}
				}
				if( pgpSigTried(rsig) && !pgpSigChecked(rsig) )
					success = FALSE;
			}
		}
		if( !success )
			pgpMarkKeyDBObjectDeleted( rsig );
	}
	return kPGPError_NoErr;
}



/*
 * Called after we have read in a PGP Key and all its children.  Check
 * it for various conditions.
 */
	PGPError
pgpKeyCleanup( PGPKeyDBObj *key, PGPBoolean trusted )
{
	return sCleanupThirdPartyRevocations( key, trusted );
}




	PGPError
pgpReadKeyFile (PGPKeyDB *kdb, PGPFile *f, PGPBoolean trusted)
{
	PGPEnv				*pgpEnv;
	PGPContextRef		context;
	PGPKeyDBObj *		topobj = NULL;
	PGPKeyDBObj *		lastobj = NULL;
	PGPKeyDBObj *		parobj = NULL;
	PGPFileOffset		pos;
	PGPSize				len;
	PGPUInt32			size;
	PGPUInt32			bodylen;
	PGPUInt32			maxbuflen = 0;
	PGPSize				len1;
	PGPInt32			pktbyte;
	PGPByte *			buf = NULL;
	PGPError			err = kPGPError_NoErr;

	context = PGPPeekKeyDBContext( kdb );
	pgpEnv = pgpContextGetEnvironment( context );

	/* Skip until we get to a key packet */
	pos = pgpFileTell( f );
	while ((pktbyte = pgpPktByteGet(f, &len, &len1, &pos)) > 0) {
		if( PKTBYTE_TYPE(pktbyte) == PKTBYTE_PUBKEY
			|| PKTBYTE_TYPE(pktbyte) == PKTBYTE_SECKEY ) {
			pgpFileSeek( f, pos, SEEK_SET );
			break;
		}
		pos = pgpFileTell( f );
	}
	/* If no key packets, return empty-handed */
	if( pktbyte < 0 )
		goto error;
									   

	/* Read each packet, add to kdb, remember where it came from */
	pos = pgpFileTell( f );
	while ((pktbyte = pgpPktByteGet(f, &len, &len1, &pos)) > 0) {
		if( len > PGPOBJ_MAXSIZE )
		{
			err = pgpFileSeek( f, len, SEEK_CUR );
			if( IsPGPError( err ) )
				goto error;
			continue;
		}
		bodylen = len;
		len += pgpPktHeaderLen( pktbyte, len );
		if( len > maxbuflen ) {
			void *vbuf = buf;
			err = pgpContextMemRealloc( context, &vbuf, len, 0 );
			buf = vbuf;
			if( IsPGPError( err ) )
			{
				err = pgpFileSeek( f, len, SEEK_CUR );
				if( IsPGPError( err ) )
					goto error;
				continue;
			}
			maxbuflen = len;
		}
		/* Put the pktbyte + length into the beginning of buf */
		pgpPktHeaderPut( buf, pktbyte, bodylen );
		size = pgpPktBodyRead( buf+len-bodylen, bodylen, len1, f );
		if( size != bodylen )
			/* Premature EOF, just return with what we have */
			break;
		size = len;

		switch (PKTBYTE_TYPE(pktbyte)) {

		  case PKTBYTE_PUBKEY:
		  case PKTBYTE_SECKEY:
			  /* Do some checks on previously read-in key certificate */
			  if( IsntNull( topobj ) )
				  pgpKeyCleanup( topobj, trusted );
			  topobj = pgpAddObject( buf, len, kdb, NULL, trusted, &err );
			  lastobj = parobj = topobj;
			  if( IsPGPError( err ) )
				  goto error;
			  break;
		  case PKTBYTE_PUBSUBKEY:
		  case PKTBYTE_SECSUBKEY:
		  case PKTBYTE_ATTRIBUTE:
		  case PKTBYTE_USERID:
			  if( IsNull(topobj) || !OBJISTOPKEY(topobj) )
				  break;
			  parobj = pgpAddObject( buf, len, kdb, topobj, trusted, &err);
			  lastobj = parobj;
			  if( IsPGPError( err ) )
				  goto error;
			  break;
		  case PKTBYTE_SIG:
			  if( IsNull(parobj) || IsNull(topobj) || !OBJISTOPKEY(topobj) )
				  break;
			  lastobj = pgpAddObject(buf, len, kdb, parobj, trusted, &err);
			  if( IsPGPError( err ) )
				  goto error;
			  break;
		  case PKTBYTE_CRL:
			  if(IsNull(parobj) || IsNull(topobj) || !OBJISTOPKEY(topobj) )
				  break;
			  if( !OBJISKEY( parobj ) )
				  parobj = topobj;
			  pgpAssert( OBJISKEY(parobj) );
			  lastobj = pgpAddObject(buf, len, kdb, parobj, trusted, &err);
			  if( IsPGPError( err ) )
				  goto error;
			  break;
		  case PKTBYTE_TRUST:
			  if( IsNull(lastobj) || !trusted )
				  break;
			  err = pgpTrustPacket( buf, len, kdb, lastobj, pgpEnv );
			  if( IsPGPError( err ) )
				  goto error;
			  break;
		  case PKTBYTE_COMMENT:
			  /* Skip this */
			  break;
		  default:
			  /* Unknown packet type; save it for output */
			  if( IsNull(parobj) )
				  break;
			  lastobj = pgpAddObject(buf, len, kdb, parobj, trusted, &err);
			  if( IsPGPError( err ) )
				  goto error;
			  break;
		}
		pos = pgpFileTell( f );
	}
 error:
	if( IsntNull( buf ) )
		PGPFreeData( buf );
	if( IsntNull( topobj ) )
		pgpKeyCleanup( topobj, trusted );
	
	return err;
}

/*
 * Add objects from back-end supplied key array.  If newobjs is false we do
 * lookups to merge them with existing keys; if true we know they are all
 * new objects and skip the lookup.
 */
	static PGPError
sAddFromKeyArray( PGPKeyDB *kdb, PGPKeyDBObj *parent, PGPKeyDBObj *prev,
	PGPUInt32 **keyArray, PGPUInt32 keyCount, PGPBoolean newobjs )
{
	PGPUInt32		i;
	PGPUInt32		id;
	PGPUInt32		flags;
	PGPUInt32		nchildren;
	PGPKeyDBObj *	obj;
	PGPError		err = kPGPError_NoErr;

	for( i = 0; i<keyCount; ++i ) {
		id = *(*keyArray)++;
		flags = *(*keyArray)++;
		if( !newobjs &&
			IsntPGPError( PGPFindNode( kdb->idToObj, id,
											 (PGPUserValue *)&obj ) ) )
		{
			/* Type should be same, except dummy top key may become subkey */
			pgpAssert( (flags & 0x3f) == (obj->objflags & 0x3f)
					   || ( (flags&0x3f)==kPGPKeyDBObjType_SubKey &&
							pgpKeyDBObjIsDummy(obj) ) );

			/*
			 * If prev is valid and we have a parent, make sure our order
			 * is correct
			 */
			if( prev != (PGPKeyDBObj *)-1UL && IsntNull( parent ) )
			{
				if( IsntNull( prev ) )
				{
					if( prev->next != obj )
					{
						if( OBJISTOPKEY( obj ) )
							pgpUnlinkKey( obj, kdb ); /* dummy to subkey */
						else
							pgpUnlinkChild( obj, parent );
						obj->next = prev->next;
						obj->up = parent;
						prev->next = obj;
					}
				} else {
					/* Null prev means we should be first child */
					if( parent->down != obj )
					{
						if( OBJISTOPKEY( obj ) )
							pgpUnlinkKey( obj, kdb ); /* dummy to subkey */
						else
							pgpUnlinkChild( obj, parent );
						obj->next = parent->down;
						obj->up = parent;
						parent->down = obj;
					}
				}
			}

			obj->objflags &= ~( kPGPKeyDBObjFlags_Deleted |
							    kPGPKeyDBObjFlags_Dummy |
							    kPGPKeyDBObjFlags_X509  | 0x3f );
			obj->objflags |= flags & ( kPGPKeyDBObjFlags_Deleted |
									   kPGPKeyDBObjFlags_Dummy |
									   kPGPKeyDBObjFlags_X509  | 0x3f );

			/* Keys may get info field changed, so force update */
			if( OBJISKEY(obj) )
				pgpKeyDBObjRefresh( obj, FALSE );

		} else {
			if( flags & kPGPKeyDBObjType_Key ) {
				obj = sNewKey( kdb );
				if ( obj == NULL )
				{
					err = kPGPError_OutOfMemory;
					goto error;
				}
				pgpLinkKey( obj, kdb );
			} else {
				if ( flags & kPGPKeyDBObjType_SubKey )
					obj = sNewSubKey( kdb );
				else if ( flags & kPGPKeyDBObjType_UserID )
					obj = sNewUserID( kdb );
				else if ( flags & kPGPKeyDBObjType_Signature )
					obj = sNewSig( kdb );
				else if ( flags & kPGPKeyDBObjType_CRL )
					obj = sNewCRL( kdb );
				else
					obj = sNewUnknown( kdb );
				if ( obj == NULL )
				{
					err = kPGPError_OutOfMemory;
					goto error;
				}
				pgpLinkChild( obj, parent );
			}
			obj->idinfo.id = id;
			obj->objflags = flags | kPGPKeyDBObjFlags_ID;
			PGPAddNode( kdb->idToObj, id, (PGPUserValue)obj );
		}
		if( !OBJISSIG( obj ) )
		{
			nchildren = *(*keyArray)++;
			err = sAddFromKeyArray( kdb, obj, NULL, keyArray,
									nchildren, newobjs );
			if( IsPGPError( err ) )
				goto error;
		}
		prev = obj;
	}
 error:
	return err;
}

	PGPError
pgpAddFromKeyArray( PGPKeyDB *kdb, PGPKeyDBObj *parent, PGPUInt32 *keyArray,
	PGPUInt32 keyCount, PGPBoolean newobjs )
{
	PGPError err;

	err = sAddFromKeyArray( kdb, parent, (PGPKeyDBObj *)-1UL,
							&keyArray, keyCount, newobjs );
	if( IsPGPError( err ) )
		return err;
	pgpKeyDBChanged( kdb, TRUE );
	return kPGPError_NoErr;
}



/*
 * Given a seckey, a keydb, and some other information, create a new

⌨️ 快捷键说明

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