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

📄 pgpx509keys.c

📁 vc环境下的pgp源码
💻 C
📖 第 1 页 / 共 5 页
字号:
sDecodeNameLong(PGPASN_CONTEXT *asnctx, PGPASN_Certificate *cert,
			PGPBoolean issuer, PGPByte *nameBuf, PGPSize *nameLength)
{
	PGPASN_Name *cname;
	PGPASN_RDNSequence *name;
	PGPASN_RelativeDistinguishedName *rdn;
	PGPASN_AttributeTypeAndValue *atv;
	PGPASN_DirectoryString *dstr;
	PGPASN_VariableBlock *vb;

	PGPBoolean sizingPass;
	PGPBoolean seenName = FALSE;
	PGPError err = kPGPError_NoErr;
	char const *oidName;
	PGPUInt32 lNameLength;
	PGPUInt32 oidLength = 0;
	PGPInt32 i, j;
	PGPInt32 twice;
	static char const dfltname[] = "(Unknown X509 name)";

	sizingPass = (nameBuf==NULL);
	lNameLength = sizingPass ? 0 : *nameLength;

	cname = issuer ? &cert->tbsCertificate.issuer
				  : &cert->tbsCertificate.subject;
	name = (PGPASN_RDNSequence *)cname->data;

	/* Make two passes, doing common name last so it shows first */
	for (twice=0; twice<2; ++twice) {
		/* Loop over elements of RDN sequence */
		for (i=0; i<name->n; ++i) {
			rdn = name->elt[i];
			for (j=0; j<rdn->n; ++j) {
				atv = rdn->elt[j];

				oidName = NULL;

				if (atv->type.len == 3
				   && atv->type.val[0] == cnoid[0]
				   && atv->type.val[1] == cnoid[1]
				   && atv->type.val[2] < sizeof(dnnames)/sizeof(dnnames[0])) {
					/* Do CN if and only if twice==1 */
					if ((atv->type.val[2] == cnoid[2]) == twice) {
						oidName = dnnames[atv->type.val[2]];
						oidLength = strlen(oidName);
					}
				}
				else if (atv->type.len == sizeof(emailoid)
					  && memcmp(atv->type.val, emailoid, atv->type.len)==0 ) {
					if (!twice) {
						oidName = emailname;
						oidLength = strlen(oidName);
					}
				}

				if( IsntNull( oidName ) ) {
					/* Look at string for value */

					pgpasn_UnpackDirectoryString( asnctx, &dstr,
										atv->value.val, atv->value.len, &err );
					if (err != 0) {
						/* Skip if unprintable string */
						err = 0;
						continue;
					}
					vb = dstr->data;

					/* Skip our inserted PGPKeyCreation string */
					if (atv->type.len == 3
					   && atv->type.val[0] == cnoid[0]
					   && atv->type.val[1] == cnoid[1]
					   && (atv->type.val[2] == 11 || atv->type.val[2] == 13)) {
						if (vb->len == sizeof(s_pgpdescr)-1 + 8 &&
							pgpMemoryEqual (vb->val, s_pgpdescr,
											sizeof(s_pgpdescr)-1) ) {
							pgpasn_FreeDirectoryString( asnctx, dstr );
							continue;
						}
					}

					seenName = TRUE;
					if (sizingPass) {
						/* add 3 for equals, comma, space */
						lNameLength += strlen(oidName) + 3;
						lNameLength += sDNQuoteString(vb->val, vb->len,
													  NULL, TRUE);
					} else {
						/* Build name string in reverse order, per LDAP */
						lNameLength -= sDNQuoteString(vb->val, vb->len,
												nameBuf+lNameLength, TRUE);
						nameBuf[--lNameLength] = '=';
						lNameLength -= oidLength;
						pgpCopyMemory( oidName, nameBuf+lNameLength,
									   oidLength );
						if( lNameLength > 0 ) {
							nameBuf[--lNameLength] = ' ';
							nameBuf[--lNameLength] = ',';
						}
					}
					pgpasn_FreeDirectoryString( asnctx, dstr );
				}
			}
		}
	}

	if( sizingPass ) {
		if (lNameLength == 0) {
			/* No name fields we recognized */
			*nameLength = sizeof(dfltname);
		} else {
			lNameLength -= 2;	/* Counted an initial ", " */
			*nameLength = lNameLength;
		}
	} else {
		/* lNameLength should have counted down to zero */
		if( !seenName ) {
			pgpAssert (lNameLength == sizeof(dfltname));
			pgpCopyMemory (dfltname, nameBuf, lNameLength);
		} else {
			pgpAssert (lNameLength == 0);
		}
	}

	return err;
}



/*
 * Convert from X.509 cert to PGP style name.  If issuer is true, we do
 * issuer's name, else subject name.
 * If namebuf is NULL, set *namelength to the necessary length.  Else
 * store the data into namebuf, and treat *namelength as an input parameter
 * telling what the length needs to be.
 * This version uses short form for X509 names, in PGP format.
 * E.g. just "John Doe <john@doe.com>".  If it can't be converted in that
 * form, it uses the long form ("C=US, etc.").
 */
static PGPError
sDecodeName(PGPASN_CONTEXT *asnctx, PGPASN_Certificate *cert,
			PGPBoolean issuer, PGPByte *nameBuf, PGPSize *nameLength)
{
#if !PGP_X509SHORTNAMES

	return sDecodeNameLong(asnctx, cert, issuer, nameBuf, nameLength);

#else /* PGP_X509SHORTNAMES */

	PGPASN_Name *cname;
	PGPASN_RDNSequence *name;
	PGPASN_RelativeDistinguishedName *rdn;
	PGPASN_AttributeTypeAndValue *atv;
	PGPASN_DirectoryString *dstr;
	PGPASN_GeneralNames *gnames;
	PGPASN_GeneralName *gname;
	PGPASN_VariableBlock *vb;
	PGPASN_Extensions *exts = cert->tbsCertificate.extensions;
	PGPASN_Extension *ext;

	PGPByte const *altnameoid;
	PGPBoolean sizingPass;
	PGPBoolean seenName = FALSE;
	PGPBoolean seenEmail = FALSE;
	PGPUInt32 lNameLength;
	PGPInt32 i, j;
	PGPError err = kPGPError_NoErr;

	sizingPass = (nameBuf==NULL);
	lNameLength = sizingPass ? 0 : *nameLength;

	cname = issuer ? &cert->tbsCertificate.issuer
				  : &cert->tbsCertificate.subject;
	name = (PGPASN_RDNSequence *)cname->data;

	/* Loop over elements of RDN sequence until seen email and name */
	for (i=0; (i<name->n) && !(seenEmail && seenName); ++i) {
		rdn = name->elt[i];
		for (j=0; (j<rdn->n) && !(seenEmail && seenName); ++j) {
			atv = rdn->elt[j];

			/* Parse attribute type */
			if (atv->type.len == sizeof(cnoid)
				&& memcmp(atv->type.val, cnoid, atv->type.len)==0 ) {
				/* Common name, followed by a string */
				pgpasn_UnpackDirectoryString( asnctx, &dstr, atv->value.val,
											  atv->value.len, &err );
				if (err != 0) {
					/* Skip if unprintable string */
					err = 0;
					continue;
				}
				vb = dstr->data;
				seenName = TRUE;
				if (sizingPass) {
					lNameLength += vb->len;
				} else {
					/* Put common name at beginning of buffer */
					pgpAssert (lNameLength >= vb->len);
					pgpCopyMemory (vb->val, nameBuf, vb->len);
					/* Add a space if needed */
					if (lNameLength > vb->len)
						nameBuf[vb->len] = ' ';
				}
				pgpasn_FreeDirectoryString( asnctx, dstr );
			} else if (atv->type.len == sizeof(emailoid)
					   && memcmp(atv->type.val, emailoid, atv->type.len)==0 ) {
				/* Email address, followed by a string */
				pgpasn_UnpackDirectoryString( asnctx, &dstr, atv->value.val,
											  atv->value.len, &err );
				if (err != 0) {
					/* Skip if unprintable string */
					err = 0;
					continue;
				}
				vb = dstr->data;
				seenEmail = TRUE;
				if (sizingPass) {
					/* Add 2 for angle brackets */
					lNameLength += vb->len + 2;
				} else {
					/* Put email address at end of buffer */
					pgpAssert (lNameLength >= vb->len+2);
					nameBuf[lNameLength-1] = '>';
					pgpCopyMemory (vb->val, nameBuf+lNameLength-1-vb->len,
								   vb->len);
					nameBuf[lNameLength-vb->len-2] = '<';
				}
				pgpasn_FreeDirectoryString( asnctx, dstr );
			}
		}
	}

	/* Check extensions to see if email is there, if not found yet */
	if (seenName && !seenEmail && IsntNull(exts)) {
		for (i=0; (i<exts->n) && !seenEmail; ++i) {
			ext = exts->elt[i];
			altnameoid = issuer ? issaltnameoid : subaltnameoid;
			/* These are same size */
			if (ext->extnID.len == sizeof(issaltnameoid)
				&& memcmp(ext->extnID.val, altnameoid, ext->extnID.len)==0 ) {
				/* Alternative name, just as we wanted */
				pgpasn_UnpackGeneralNames( asnctx, &gnames, ext->extnValue.val,
										   ext->extnValue.len, &err );
				if (err != 0) {
					/* Skip if unprintable string */
					err = 0;
					continue;
				}
				for (j=0; (j<gnames->n) && !seenEmail; ++j) {
					gname = gnames->elt[j];
					if (gname->CHOICE_field_type != ASN_GENERALNAME_RFC822NAME)
						continue;
					/* Okay, we have an email address */
					vb = gname->data;
					seenEmail = TRUE;
					if (sizingPass) {
						/* Add 2 for angle brackets */
						lNameLength += vb->len + 2;
					} else {
						/* Put email address at end of buffer */
						pgpAssert (lNameLength >= vb->len+2);
						nameBuf[lNameLength-1] = '>';
						pgpCopyMemory (vb->val, nameBuf+lNameLength-1-vb->len,
									   vb->len);
						nameBuf[lNameLength-vb->len-2] = '<';
					}
				}
				pgpasn_FreeGeneralNames( asnctx, gnames );
			}
		}
	}

	if (!seenName || !seenEmail) {
		/* If we could not parse the name, use the long form */
		return sDecodeNameLong(asnctx, cert, issuer, nameBuf, nameLength);
	}

	if( sizingPass ) {
		/* Count a space between name and email if have both */
		if (seenName && seenEmail)
			++lNameLength;
		*nameLength = lNameLength;
	}

	return err;

#endif /* PGP_X509SHORTNAMES */
}



/*
 * Create a PGP public key packet corresponding to the certificate, or a
 * private key packet corresponding to the PrivateKeyInfo.  Only one of
 * these two pointers should be non-NULL.
 *
 * If keybuf is NULL, set *keylength to the necessary length.  Else
 * store the data into keybuf, and treat *keylength as an input parameter
 * telling what the length needs to be.
 */
static PGPError
sDecodeKey(PGPContextRef context, PGPASN_CONTEXT *asnctx,
	PGPASN_Certificate *cert, PGPASN_PrivateKeyInfo *pinfo,
	PGPByte *keyBuf, PGPSize *keyLength)
{
	PGPASN_SubjectPublicKeyInfo *spki =
					&cert->tbsCertificate.subjectPublicKeyInfo;
	PGPASN_DssParms			*dssp = NULL;
	PGPASN_DSAPublicKey		*dssk = NULL;
	PGPASN_ELGParms			*elgp = NULL;
	PGPASN_ELGPublicKey		*elgk = NULL;
	PGPASN_RSAKey			*rsak = NULL;
	PGPASN_PrivateKey		*pkey;
	PGPASN_RSAPrivateKey	*rsapriv = NULL;

	PGPPublicKeyAlgorithm keyalgorithm;
	PGPByte *bnbuf[6];		/* buf offset for start of X.509 bignum */
	PGPSize bnlen[6];		/* buf length for X.509 bignum */
	PGPSize bnlength[6];	/* length of PGP encoded bignum */
	PGPUInt32 pubelems=0;	/* Number of bignum elements that are public */
	PGPUInt32 i, j, o;
	PGPUInt16 checksum;
	PGPSize keybuflength;
	PGPByte *pubbuf = NULL;
	PGPSize publength;
	PGPByte keyversion;
	PGPByte const *matchkeybuf = NULL;
	PGPSize matchkeybuflength;
	RingObject *matchkey;
	PGPMemoryMgrRef mgr = PGPGetContextMemoryMgr( context );
	RingPool *pool = pgpContextGetRingPool( context );
	PGPByte hash20[20];
	PGPError err = kPGPError_NoErr;

	/* Init bignum arrays */
	pgpClearMemory (bnbuf, sizeof(bnbuf));
	pgpClearMemory (bnlen, sizeof(bnlen));
	pgpClearMemory (bnlength, sizeof(bnlength));

	if (IsntNull( pinfo ) ) {
		/* Do private key */

		/* Decode object identifier for RSA/DSS/ElGamal */
		err = sDecodeAlgorithmOID ( asnctx,
									&pinfo->privateKeyAlgorithm.algorithm,
									&keyalgorithm, NULL );
		if( IsPGPError(err) )
			goto error;

		if (keyalgorithm == kPGPPublicKeyAlgorithm_RSA) {
			pkey = &pinfo->privateKey;
			pgpasn_UnpackRSAPrivateKey( asnctx, &rsapriv,
										pkey->val, pkey->len, &err);
			CHKASNERR(err);

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

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

			/* private exponent d */
			bnbuf[2] = rsapriv->privateExponent.val;
			bnlen[2] = rsapriv->privateExponent.len;
			err = sDecodeX509Integer (bnbuf[2], bnlen[2], NULL, &bnlength[2]);
			if( IsPGPError( err ) )
				goto error;

			/* smaller prime */
			bnbuf[3] = rsapriv->prime2.val;
			bnlen[3] = rsapriv->prime2.len;
			err = sDecodeX509Integer (bnbuf[3], bnlen[3], NULL, &bnlength[3]);
			if( IsPGPError( err ) )
				goto error;

			/* larger prime */
			bnbuf[4] = rsapriv->prime1.val;
			bnlen[4] = rsapriv->prime1.len;
			err = sDecodeX509Integer (bnbuf[4], bnlen[4], NULL, &bnlength[4]);
			if( IsPGPError( err ) )
				goto error;

			/* inverse u of smaller prime mod larger prime */
			bnbuf[5] = rsapriv->coefficient.val;
			bnlen[5] = rsapriv->coefficient.len;
			err = sDecodeX509Integer (bnbuf[5], bnlen[5], NULL, &bnlength[5]);
			if( IsPGPError( err ) )
				goto error;

			/* Number of these values which are public */
			pubelems = 2;

		} else if (keyalgorithm == kPGPPublicKeyAlgorithm_ElGamal) {
			pgpAssert (0);
		} else /* DSS */ {
			pgpAssert (0);
		}

	} else {
		/* Do public key */
		/* Decode object identifier for RSA/DSS/ElGamal */
		err = sDecodeAlgorithmOID ( asnctx, &spki->algorithm.algorithm,
									&keyalgorithm, NULL );
		if( IsPGPError(err) )
			goto error;

		if (keyalgorithm == kPGPPublicKeyAlgorithm_DSA) {
			pgpasn_UnpackDssParms ( asnctx, &dssp,
									spki->algorithm.parameters->val,
									spki->algorithm.parameters->len, &err );
			CHKASNERR( err );
			pgpasn_UnpackDSAPublicKey ( asnctx, &dssk,
										spki->subjectPublicKey.val,
										spki->subjectPublicKey.len, &err );
			CHKASNERR( err );

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

			/* subprime q */
			bnbuf[1] = dssp->q.val;
			bnlen[1] = dssp->q.len;
			err = sDecodeX509Integer (bnbuf[1], bnlen[1], NULL, &bnlength[1]);
			if( IsPGPError( err ) )
				goto error;

			/* generator g */
			bnbuf[2] = dssp->g.val;
			bnlen[2] = dssp->g.len;
			err = sDecodeX509Integer (bnbuf[2], bnlen[2], NULL, &bnlength[2]);
			if( IsPGPError( err ) )
				goto error;

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

			pubelems = 4;

		} else if (keyalgorithm == kPGPPublicKeyAlgorithm_ElGamal) {
			pgpasn_UnpackELGParms ( asnctx, &elgp,
									spki->algorithm.parameters->val,
									spki->algorithm.parameters->len, &err );
			CHKASNERR( err );
			pgpasn_UnpackELGPublicKey ( asnctx, &elgk,
										spki->subjectPublicKey.val,
										spki->subjectPublicKey.len, &err );
			CHKASNERR( err );

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

			/* generator g */
			bnbuf[1] = elgp->g.val;

⌨️ 快捷键说明

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