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

📄 pgpx509keys.c

📁 vc环境下的pgp源码
💻 C
📖 第 1 页 / 共 5 页
字号:
			bnlen[1] = elgp->g.len;
			err = sDecodeX509Integer (bnbuf[1], bnlen[1], NULL, &bnlength[1]);
			if( IsPGPError( err ) )
				goto error;

			/* public value y */
			bnbuf[2] = elgk->val;
			bnlen[2] = elgk->len;
			err = sDecodeX509Integer (bnbuf[2], bnlen[2], NULL, &bnlength[2]);
			if( IsPGPError( err ) )
				goto error;

			pubelems = 3;

		} else /* RSA */ {
			pgpasn_UnpackRSAKey ( asnctx, &rsak, spki->subjectPublicKey.val,
								  spki->subjectPublicKey.len, &err );
			CHKASNERR( err );

			/* modulus n */
			bnbuf[0] = rsak->modulus.val;
			bnlen[0] = rsak->modulus.len;
			err = sDecodeX509Integer (bnbuf[0], bnlen[0], NULL, &bnlength[0]);
			if( IsPGPError( err ) )
				goto error;

			/* exponent e */
			bnbuf[1] = rsak->exponent.val;
			bnlen[1] = rsak->exponent.len;
			err = sDecodeX509Integer (bnbuf[1], bnlen[1], NULL, &bnlength[1]);
			if( IsPGPError( err ) )
				goto error;
			pubelems = 2;
		}
	}

	keybuflength = 0;
	publength = 0;
	for (i=0; i<elemsof(bnlength); ++i) {
		if( bnlength[i] == 0 )
			break;
		if (i < pubelems)
			publength += bnlength[i];
		keybuflength += bnlength[i];
	}

	/*
	 * To better estimate keybuflength, we need to construct the numeric
	 * data portion and then see if it matches an incoming key.  Only then
	 * can we know what kind of key packet we are dealing with.
	 */

	pubbuf = PGPNewData (mgr, publength, 0);
	CHKNONNULL(pubbuf, err);
	o = 0;
	for (i=0; i<pubelems; ++i) {
		if( bnlength[i] == 0 )
			break;
		err = sDecodeX509Integer (bnbuf[i], bnlen[i],
								  pubbuf+o, &bnlength[i]);
		if( IsPGPError( err ) )
			goto error;
		o += bnlength[i];
	}
	pgpAssert (o == publength);

	/* Get hash of numeric data */
	pgpFingerprint20HashBuf (context, pubbuf, publength, hash20);

	/* See if this matches an existing key */
	matchkey = ringPoolFindKey20n (pool, hash20);

	if( IsNull( matchkey ) ) {
		/* Fall back on defaults */
		if (keyalgorithm == kPGPPublicKeyAlgorithm_RSA)
			keyversion = PGPVERSION_3;
		else
			keyversion = PGPVERSION_4;
	} else {
		RingSet *allset;
		allset = ringSetCreateUniversal (pool);
		if( IsNull( allset ) ) {
			err = ringPoolError(pool)->error;
			goto error;
		}
		matchkeybuf = ringFetchObject (allset, matchkey, &matchkeybuflength);
		ringSetDestroy( allset );
		if( IsNull( matchkeybuf ) ) {
			ringSetDestroy( allset );
			err = ringPoolError(pool)->error;
			goto error;
		}
		keyversion = matchkeybuf[0];
	}

	keybuflength += 6;	/* bytes preceding bignums */
	if( keyversion <= PGPVERSION_3)
			keybuflength += 2;	/* room for expiration date */

	if( IsntNull( pinfo ) ) {
		/*
		 * Can only import private if we have a matching key,
		 * because we can't synthesize a userid for it
		 */
		if( IsNull( matchkey ) ) {
			err = kPGPError_PublicKeyNotFound;
			goto error;
		}
		keybuflength += 3;		/* Private adds 1 enc byte + 2 csum */
	}

	if( IsNull( keyBuf ) ) {
		*keyLength = keybuflength;
	} else {
		pgpAssert (*keyLength == keybuflength);
		/* public key packet */
		o = 0;
		keyBuf[o++] = keyversion;
		/* 1-4 are timestamp */
		if (IsntNull( matchkey ) ) {
			pgpCopyMemory (matchkeybuf+1, keyBuf+o, 4);
		} else {
			PGPUInt32 creation = sDecodeKeyCreation( asnctx, cert );
			if( creation != 0 ) {
				keyBuf[o+0] = (creation >> 24) & 0xff;
				keyBuf[o+1] = (creation >> 16) & 0xff;
				keyBuf[o+2] = (creation >>  8) & 0xff;
				keyBuf[o+3] = (creation >>  0) & 0xff;
			} else {
				/* Use certificate creation date if all else fails */
				err = sDecodeNotBefore4( asnctx, cert, keyBuf+o );
				if (IsPGPError( err ) ) {
					pgpClearMemory (keyBuf+o, 4);
					err = kPGPError_NoErr;
				}
			}
		}
		o += 4;
		/* Next two are expiration if V3 packets */
		if (keyversion <= PGPVERSION_3) {
			if (IsntNull( matchkey ) ) {
				pgpCopyMemory (matchkeybuf+5, keyBuf+o, 2);
			} else {
				pgpClearMemory (keyBuf+o, 2);
			}
			o += 2;
		}
		keyBuf[o++] = keyalgorithm;
		pgpCopyMemory (pubbuf, keyBuf+o, publength);
		o += publength;
		PGPFreeData( pubbuf );
		pubbuf = NULL;

		if( IsntNull( pinfo ) ) {
			/* Save secret key fields */
			keyBuf[o++] = '\0';		/* Unencrypted secret data */
			checksum = 0;
			for (i=pubelems; i<elemsof(bnlength); ++i) {
				if( bnlength[i] == 0 )
					break;
				err = sDecodeX509Integer (bnbuf[i], bnlen[i],
										  keyBuf+o, &bnlength[i]);
				if( IsPGPError( err ) )
					goto error;
				for (j=0; j<bnlength[i]; ++j)
					checksum += keyBuf[o+j];
				o += bnlength[i];
			}
			keyBuf[o++] = (checksum >> 8) & 0xff;
			keyBuf[o++] = (checksum >> 0) & 0xff;
		}

		pgpAssert (o == keybuflength);
	}

error:

	if( IsntNull( pubbuf ) )
		PGPFreeData( pubbuf );
	if( IsntNull( dssp ) )
		pgpasn_FreeDssParms( asnctx, dssp );
	if( IsntNull( dssk ) )
		pgpasn_FreeDSAPublicKey( asnctx, dssk );
	if( IsntNull( elgp ) )
		pgpasn_FreeELGParms( asnctx, elgp );
	if( IsntNull( elgk ) )
		pgpasn_FreeELGPublicKey( asnctx, elgk );
	if( IsntNull( rsak ) )
		pgpasn_FreeRSAKey( asnctx, rsak );
	if( IsntNull( rsapriv ) )
		pgpasn_FreeRSAPrivateKey( asnctx, rsapriv );

	return err;
}


/*
 * Given an X509 cert, return a PGPKeySetRef containing a simple PGP key
 * with the same key material as the original cert.  The userid on the
 * key is one of the 509 subject distinguished name fields, the common name
 * if it exists, else one of the other fields.
 */
static PGPError
sDecode509(PGPContextRef context, PGPASN_CONTEXT *asnctx,
		   PGPASN_Certificate *cert, PGPKeySetRef *kset)
{
	PGPMemoryMgrRef mgr;
	PGPByte *pgpkeybuf = NULL;
	PGPSize keylen;
	PGPSize namelen;
	PGPSize siglen;
	PGPSize pgpkeylen;
	PGPUInt32 o;
	PGPKeySetRef keyset;
	PGPError err = kPGPError_NoErr;

	*kset = NULL;
	mgr = PGPGetContextMemoryMgr( context );

	/* Decode signature packet */
	err = sDecodeSig (context, asnctx, cert, SIGSUBSUB_X509_VERSION_LO,
					  NULL, &siglen);
	if (IsPGPError(err))
		goto error;

	/* Decode subject name */
	err = sDecodeName (asnctx, cert, FALSE, NULL, &namelen);
	if (IsPGPError(err))
		goto error;
	
	/* Decode key packet */
	err = sDecodeKey (context, asnctx, cert, NULL, NULL, &keylen);
	if (IsPGPError(err))
		goto error;

	/* Now create the PGP key */

	pgpkeylen = 3 + keylen + 3 + namelen + ((siglen>0)?(3+siglen):0);
	pgpkeybuf = (PGPByte *) PGPNewData( mgr, pgpkeylen, 0 );
	CHKNONNULL (pgpkeybuf, err);

	/* public key packet */
	o = 0;
	pgpkeybuf[o++] = PKTBYTE_BUILD(PKTBYTE_PUBKEY, 1),
	pgpkeybuf[o++] = (keylen >> 8) & 0xff;
	pgpkeybuf[o++] = (keylen >> 0) & 0xff;
	err = sDecodeKey (context, asnctx, cert, NULL, pgpkeybuf + o, &keylen);
	if (IsPGPError(err))
		goto error;
	o += keylen;

	/* userid packet */
	pgpkeybuf[o++] = PKTBYTE_BUILD(PKTBYTE_NAME, 1);
	pgpkeybuf[o++] = (namelen >> 8) & 0xff;
	pgpkeybuf[o++] = (namelen >> 0) & 0xff;
	err = sDecodeName (asnctx, cert, FALSE, pgpkeybuf + o, &namelen);
	if (IsPGPError(err))
		goto error;
	o += namelen;

	/* sig packet */
	pgpkeybuf[o++] = PKTBYTE_BUILD(PKTBYTE_SIG, 1);
	pgpkeybuf[o++] = (siglen >> 8) & 0xff;
	pgpkeybuf[o++] = (siglen >> 0) & 0xff;
	err = sDecodeSig (context, asnctx, cert, SIGSUBSUB_X509_VERSION_LO,
					  pgpkeybuf + o, &siglen);
	if (IsPGPError(err))
		goto error;
	o += siglen;

	pgpAssert (o == pgpkeylen);

	err = pgpImportKeyBinary( context, pgpkeybuf, pgpkeylen, &keyset );
	if( IsPGPError( err ) )
		goto error;

	*kset = keyset;
	/* Fall through */
error:

	if( IsntNull(pgpkeybuf) )
		PGPFreeData( pgpkeybuf );
	return err;
}


/* Entry point to import a 509 cert from the specified location */
	PGPError
pgpDecodeX509Cert( PGPByte *buf, PGPSize len, PGPContextRef context,
				   PGPKeySetRef *keys )
{
	PGPASN_Certificate *cert;
	PGPMemoryMgrRef	mgr;
	PGPASN_CONTEXT	asnctx_static, *asnctx = &asnctx_static;
	PGPASN_MemoryMgr asnmem;
	PGPError		err = kPGPError_NoErr;
	
	mgr = PGPGetContextMemoryMgr( context );
	sSetupASNCONTEXT (mgr, asnctx, &asnmem);

	pgpasn_UnpackCertificate( asnctx, &cert, buf, len, &err );
	CHKASNERR( err )

	err = sDecode509( context, asnctx, cert, keys);

	pgpasn_FreeCertificate( asnctx, cert );

error:

	return err;
}

/* Entry point to import a SET OF X509 certs */
	PGPError
pgpDecodeX509CertSet(PGPByte *buf, PGPSize len, PGPContextRef context,
					 PGPKeySetRef *kset)
{
	PGPASN_Certificates *certs = NULL;
	PGPASN_Certificate *cert;
	PGPMemoryMgrRef	mgr;
	PGPASN_CONTEXT	asnctx_static, *asnctx = &asnctx_static;
	PGPASN_MemoryMgr asnmem;
	PGPKeySetRef	newkset = NULL;
	PGPKeySetRef	tmpkset = NULL;
	PGPInt32		i;
	PGPError		err = kPGPError_NoErr;

	mgr = PGPGetContextMemoryMgr( context );
	sSetupASNCONTEXT (mgr, asnctx, &asnmem);
	pgpAssert( IsntNull( kset ) );
	*kset = NULL;

	if( IsPGPError( err = PGPNewKeySet( context, &newkset ) ) )
		goto error;

	pgpasn_UnpackCertificates( asnctx, &certs, buf, len, &err );
	CHKASNERR( err );

	for (i=0; i<certs->n; ++i) {
		cert = certs->elt[i];
		err = sDecode509( context, asnctx, cert, &tmpkset );
		CHKASNERR( err );
		PGPAddKeys( tmpkset, newkset );
		PGPCommitKeyRingChanges( newkset );
		PGPFreeKeySet( tmpkset );
		tmpkset = NULL;
	}

error:
	if( IsntNull( certs ) )
		pgpasn_FreeCertificates( asnctx, certs );
	if( IsntNull( tmpkset ) )
		PGPFreeKeySet( tmpkset );

	if( IsntPGPError( err ) )
		*kset = newkset;
	else if( IsntNull( newkset ) )
		PGPFreeKeySet( newkset );

	return err;
}


/* Entry point to import a SET OF X509 CRLs */
	PGPError
pgpDecodeX509CRLSet(PGPByte *buf, PGPSize len,
					PGPContextRef context, PGPKeySet *kset)
{
	PGPASN_CertificateRevocationLists *crls = NULL;
	PGPASN_CertificateRevocationList *crl;
	PGPASN_Extension *ext;
	PGPASN_DistributionPointName *dpname;
	PGPASN_GeneralNames *gnames;
	PGPASN_IssuingDistributionPoint *dpt = NULL;
	PGPMemoryMgrRef	mgr;
	PGPASN_CONTEXT	asnctx_static, *asnctx = &asnctx_static;
	PGPASN_MemoryMgr asnmem;
	RingPool *pool = pgpContextGetRingPool( context );
	RingSet *newset = NULL;
	RingObject *crlkey;
	RingObject *crlobj;
	PGPPubKey *pubkey = NULL;
	PGPByte *pgpcrlbuf = NULL;
	PGPSize pgpcrllen;
	PGPByte *crlbuf = NULL;
	PGPSize crllen;
	PGPByte *namebuf = NULL;
	PGPSize namebuflen;
	PGPByte *dpoint = NULL;		/* Dynamically allocated */
	PGPSize dpointlen;
	PGPInt32		i, j;
	PGPError		err = kPGPError_NoErr;

	mgr = PGPGetContextMemoryMgr( context );
	sSetupASNCONTEXT (mgr, asnctx, &asnmem);

	pgpasn_UnpackCertificateRevocationLists( asnctx, &crls, buf, len, &err );
	CHKASNERR( err );

	newset = ringSetCreate( pool );
	if( IsNull( newset ) ) {
		err = ringPoolError(pool)->error;
		goto error;
	}

	for (i=0; i<crls->n; ++i) {
		crl = crls->elt[i];
		/* Look up CRL to see if we have issuing key */
		namebuflen = pgpasn_SizeofName( asnctx,
										&crl->tbsCertList.issuer, TRUE );
		namebuf = (PGPByte *) PGPNewData( mgr, namebuflen, 0 );
		CHKNONNULL( namebuf, err );
		pgpasn_PackName (asnctx, namebuf, namebuflen, &crl->tbsCertList.issuer,
						 &err );
		CHKASNERR( err );

		crlkey = ringPoolFindX509NamedSig (pool, namebuf, namebuflen);
		PGPFreeData( namebuf );
		namebuf = NULL;

		if( IsNull( crlkey ) ) {
			/* Don't have a key the CRL is for, skip it! */
			continue;
		}

		ringSetAddObject( newset, crlkey );

		/* Actualy the above call returns a sig on the key we want */
		pgpAssert( OBJISSIG( crlkey ) );
		while (!OBJISTOPKEY( crlkey ) )
			crlkey = crlkey->g.up;

		/* See if CRL is properly signed */
		pubkey = ringKeyPubKey(newset, crlkey, PGP_PKUSE_SIGN);
		if (!pubkey) {
			/* Can't verify this sig for some reason, try next */
			continue;
		}
		crllen = pgpasn_SizeofCertificateRevocationList( asnctx, crl, TRUE );
		crlbuf = (PGPByte *) PGPNewData( mgr, crllen, TRUE );
		CHKNONNULL( crlbuf, err );
		pgpasn_PackCertificateRevocationList( asnctx, crlbuf, crllen, crl,
											  &err );
		CHKASNERR( err );
		err = pgpX509VerifySignedObject( context, pubkey, crlbuf, crllen );
		PGPFreeData( crlbuf );
		crlbuf = NULL;
		pgpPubKeyDestroy( pubkey );
		pubkey = NULL;

		if( IsPGPError( err ) ) {
			/* Couldn't verify sig, skip CRL */
			err = kPGPError_NoErr;
			continue;
		}

		/* See if CRL has distribution point */
		dpoint = NULL;
		dpointlen = 0;
		if( IsntNull( crl->tbsCertList.crlExtensions ) ) {
			for (j=0; j<crl->tbsCertList.crlExtensions->n; ++j) {
				ext = crl->tbsCertList.crlExtensions->elt[j];
				if (ext->extnID.len == sizeof(issdistpoint)
					&& memcmp(ext->extnID.val, issdistpoint,
							  ext->extnID.len)==0 ) {
					/* Parse distribution point */
					pgpasn_UnpackIssuingDistributionPoint ( asnctx, &dpt,
								ext->extnValue.val, ext->extnValue.len, &err );
					if( err == 0 &&
								IsntNull( dpt->distributionPoint ) ) {
						

⌨️ 快捷键说明

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