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

📄 pgpx509keys.c

📁 vc环境下的pgp源码
💻 C
📖 第 1 页 / 共 5 页
字号:
	vbuf[o++] = 5;	/* length */
	vbuf[o++] = SIGSUB_CREATION;
	vbuf[o++] = (PGPByte)(creationtime >> 24);
	vbuf[o++] = (PGPByte)(creationtime >> 16);
	vbuf[o++] = (PGPByte)(creationtime >>  8);
	vbuf[o++] = (PGPByte)(creationtime >>  0);

	vbuf[o++] = 5;	/* length */
	vbuf[o++] = SIGSUB_EXPIRATION;
	vbuf[o++] = (PGPByte)(expirationtime >> 24);
	vbuf[o++] = (PGPByte)(expirationtime >> 16);
	vbuf[o++] = (PGPByte)(expirationtime >>  8);
	vbuf[o++] = (PGPByte)(expirationtime >>  0);

	pgpAssert (o == *vlength);

error:

	return err;
}

/*
 * Extract cert NotBefore time as a four byte time value, in bigendian form.
 */
static PGPError
sDecodeNotBefore4(PGPASN_CONTEXT *asnctx, PGPASN_Certificate *cert,
				  PGPByte *cbuf)
{
	PGPASN_Validity *val = &cert->tbsCertificate.validity;
	PGPASN_CertificateValidityDate *cvd;
	PGPASN_UTCTime *utc;
	PGPUInt32 creationtime;
	PGPError err = kPGPError_NoErr;

	(void)asnctx;

	cvd = &val->notBefore;
	utc = (PGPASN_UTCTime *)cvd->data;
	err = sDecodeUTCTime (utc->val, utc->len,
					(PGPBoolean)(cvd->CHOICE_field_type!=PGPASN_ID_UTCTime),
					&creationtime);
	if( IsPGPError( err ) )
		goto error;

	*cbuf++ = (creationtime >> 24) & 0xff;
	*cbuf++ = (creationtime >> 16) & 0xff;
	*cbuf++ = (creationtime >>  8) & 0xff;
	*cbuf++ = (creationtime >>  0) & 0xff;

error:

	return err;
}


/*
 * Convert from X.509 cert to PGP signature level subpacket, if any.
 * If slbuf is NULL, set *sllength to the necessary length.  Else
 * store the data into slbuf, and treat *sllength as an input parameter
 * telling what the length needs to be.
 * We optionally create a PGP sig-level subpacket if it is a CA certificate.
 */
static PGPError
sDecodeSigLevel(PGPContextRef context, PGPASN_CONTEXT *asnctx,
				PGPASN_Certificate *cert, PGPByte *slbuf, PGPSize *sllength)
{
	PGPASN_Extensions *exts = cert->tbsCertificate.extensions;
	PGPASN_Extension *ext;
	PGPASN_BasicConstraints *bc;
	PGPUInt32 o;
	PGPInt32 i;
	PGPInt32 level = 0;
	PGPBoolean gotCA = FALSE;
	RingPool *pool = pgpContextGetRingPool( context );
	PGPError err = kPGPError_NoErr;

	pgpAssert( IsntNull( sllength ) );

	/* Nothing to do if no extensions */
	if (!exts) {
		if( IsNull( slbuf ) ) {
			*sllength = 0;
		}
		return kPGPError_NoErr;
	}

	for (i=0; (i<exts->n) && !gotCA; ++i) {
		ext = exts->elt[i];
		if (ext->extnID.len == sizeof(bconstraintsoid)
			&& memcmp(ext->extnID.val, bconstraintsoid, ext->extnID.len)==0 ) {
			/* Have a BasicConstraints extension */
			pgpasn_UnpackBasicConstraints( asnctx, &bc, ext->extnValue.val,
										   ext->extnValue.len, &err );
			if (err != 0) {
				/* Skip if no good */
				err = 0;
				continue;
			}
			if ( IsntNull (bc->cA) && pgpasn_GetBoolVal( asnctx, bc->cA ) ) {
				/* Here we have it as a CA.  Assume maximum level */
				if (IsNull( bc->pathLenConstraint) ) {
					/* Max level if unconstrained */
					level = 255;
				} else {
					level = pgpasn_GetIntVal( asnctx, bc->pathLenConstraint,
											  &err );
					if( err ) {
						/* Skip the whole thing if malformed */
						err = 0;
						pgpasn_FreeBasicConstraints( asnctx, bc );
						continue;
					}
					/* In our units we use one level larger */
					level += 1;
				}
				gotCA = TRUE;
			}
			pgpasn_FreeBasicConstraints( asnctx, bc );
		}
	}

	if (!gotCA) {
		if( IsNull( slbuf ) ) {
			*sllength = 0;
		}
		return kPGPError_NoErr;
	}

	/* Here we need to create a sig level packet */
	if( IsNull( slbuf ) ) {
		/* One byte of len, one of type, one of level, one of trust */
		*sllength = 4;
		return kPGPError_NoErr;
	}

	pgpAssert (*sllength == 4);

	o = 0;
	slbuf[o++] = 3;	/* length */
	slbuf[o++] = SIGSUB_TRUST;
	slbuf[o++] = level;
	slbuf[o++] = ringTrustOldToExtern( pool, kPGPKeyTrust_Complete );

	pgpAssert (o == *sllength);

	return err;
}


/*
 * Convert from X.509 cert to PGP key usage subpacket, if any.
 * If kubuf is NULL, set *kulength to the necessary length.  Else
 * store the data into kubuf, and treat *kulength as an input parameter
 * telling what the length needs to be.
 * We optionally create a PGP sig-level subpacket if it is a CA certificate.
 */
static PGPError
sDecodeKeyUsage(PGPASN_CONTEXT *asnctx,
				PGPASN_Certificate *cert, PGPByte *kubuf, PGPSize *kulength)
{
	PGPASN_Extensions *exts = cert->tbsCertificate.extensions;
	PGPASN_Extension *ext;
	PGPASN_KeyUsage *ku;
	PGPUInt32 o;
	PGPInt32 i;
	PGPUInt32 kbits, kusage = 0;
	PGPBoolean gotKU = FALSE;
	PGPError err = kPGPError_NoErr;

	pgpAssert( IsntNull( kulength ) );

	/* Nothing to do if no extensions */
	if (!exts) {
		if( IsNull( kubuf ) ) {
			*kulength = 0;
		}
		return kPGPError_NoErr;
	}

	for (i=0; (i<exts->n) && !gotKU; ++i) {
		ext = exts->elt[i];
		if (ext->extnID.len == sizeof(keyusageoid)
			&& memcmp(ext->extnID.val, keyusageoid, ext->extnID.len)==0 ) {
			/* Have a KeyUsage extension */
			pgpasn_UnpackKeyUsage( asnctx, &ku, ext->extnValue.val,
								   ext->extnValue.len, &err );
			if (err != 0) {
				/* Skip if no good */
				err = 0;
				continue;
			}
			/* Coerce as an int value to get the bits */
			kbits = pgpasn_GetIntVal( asnctx,
									  (PGPASN_VariableBlock *)ku, &err );
			if (err != 0) {
				/* Skip if no good */
				err = 0;
				pgpasn_FreeKeyUsage( asnctx, ku );
				continue;
			}
			kusage = 0;
			if (kbits & (PGPASN_KeyUsage_digitalSignature |
						 PGPASN_KeyUsage_nonRepudiation))
				kusage |= SIGSUBF_KEYFLAG0_USAGE_SIGN;
			if (kbits & (PGPASN_KeyUsage_keyEncipherment |
						 PGPASN_KeyUsage_dataEncipherment |
						 PGPASN_KeyUsage_keyAgreement))
				kusage |= SIGSUBF_KEYFLAG0_USAGE_ENCRYPT_COMM |
						  SIGSUBF_KEYFLAG0_USAGE_ENCRYPT_STORAGE;
			if (kbits & (PGPASN_KeyUsage_keyCertSign |
						 PGPASN_KeyUsage_cRLSign))
				kusage |= SIGSUBF_KEYFLAG0_USAGE_CERTIFY;
			gotKU = TRUE;
			pgpasn_FreeKeyUsage( asnctx, ku );
		}
	}

	if (!gotKU) {
		if( IsNull( kubuf ) ) {
			*kulength = 0;
		}
		return kPGPError_NoErr;
	}

	/* Here we need to create a key usage packet */
	if( IsNull( kubuf ) ) {
		/* One byte of len, one of type, one of usage */
		*kulength = 3;
		return kPGPError_NoErr;
	}

	pgpAssert (*kulength == 3);

	o = 0;
	kubuf[o++] = 2;	/* length */
	kubuf[o++] = SIGSUB_KEYFLAGS;
	kubuf[o++] = kusage;

	pgpAssert (o == *kulength);

	return err;
}

/*
 * Extract PGP Key Creation field from cert, if available.
 * Return zero if not.
 * We try to encode it in the Description or, failing that, OrgUnit
 * fields of the subject DN.
 * If not there, we look for our custom extension.
 */
static PGPUInt32
sDecodeKeyCreation(PGPASN_CONTEXT *asnctx, PGPASN_Certificate *cert)
{
	PGPASN_RDNSequence *name;
	PGPASN_RelativeDistinguishedName *rdn;
	PGPASN_AttributeTypeAndValue *atv;
	PGPASN_DirectoryString *dstr;
	PGPASN_VariableBlock *vb;
	PGPASN_Extensions *exts;
	PGPASN_Extension *ext;
	PGPASN_PGPExtension *pe;
	PGPASN_UTCTime *utc;
	PGPUInt32 dateval = 0;
	PGPBoolean found;
	PGPInt32 i, j, k;
	char *bf;
	PGPError err = kPGPError_NoErr;

	found = FALSE;
	name = (PGPASN_RDNSequence *)cert->tbsCertificate.subject.data;
	/* Loop over elements of RDN sequence */
	for (i=0; i<name->n && !found; ++i) {
		rdn = name->elt[i];
		for (j=0; j<rdn->n && !found; ++j) {
			atv = rdn->elt[j];

			/* Look for OU or Description */
			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)) {

				pgpasn_UnpackDirectoryString( asnctx, &dstr,
							atv->value.val, atv->value.len, &err );
				if (err != 0) {
					/* Skip if unprintable string */
					err = 0;
					continue;
				}
				vb = dstr->data;
				if (vb->len == sizeof(s_pgpdescr)-1 + 8 &&
					pgpMemoryEqual (vb->val, s_pgpdescr,
									sizeof(s_pgpdescr)-1) ) {
					/* Have a match, parse date value */
					found = TRUE;
					bf = (char *)vb->val + sizeof(s_pgpdescr)-1;
					for (k=0; k<8; ++k) {
						dateval = (dateval << 4) |
							((bf[k] <= '9') ? (bf[k] - '0')
							 : (bf[k] <= 'F') ? (bf[k] - 'A' + 10)
							 : (bf[k] - 'a' + 10));
					}
					pgpasn_FreeDirectoryString( asnctx, dstr );
					break;
				}
				pgpasn_FreeDirectoryString( asnctx, dstr );
			}
		}
	}

	if (found)
		return dateval;

	/* Now check extensions */
	
	exts = cert->tbsCertificate.extensions;
	if (IsNull(exts))
		return dateval;

	/* Check extensions for PGP special */
	for (i=0; i<exts->n && !found; ++i) {
		ext = exts->elt[i];
		if (ext->extnID.len == sizeof(pgpextensionoid)
			&& memcmp(ext->extnID.val, pgpextensionoid, ext->extnID.len)==0 ) {
			/* Have a match */
			pgpasn_UnpackPGPExtension( asnctx, &pe,
							ext->extnValue.val, ext->extnValue.len, &err );
			if (err != 0) {
				/* Skip if can't handle */
				err = 0;
				continue;
			}
			utc = (PGPASN_UTCTime *)pe->keyCreation.data;
			err = sDecodeUTCTime (utc->val, utc->len,
					(PGPBoolean)
					(pe->keyCreation.CHOICE_field_type!=PGPASN_ID_UTCTime),
					&dateval);
			if (err == kPGPError_NoErr)
				found = TRUE;
			pgpasn_FreePGPExtension( asnctx, pe );
		}
	}

	return dateval;
}




/*
 * Convert from X.509 cert to PGP style sig packet.
 * If sigbuf is NULL, set *siglength to the necessary length.  Else
 * store the data into sigbuf, and treat *siglength as an input parameter
 * telling what the length needs to be.
 */
static PGPError
sDecodeSig(PGPContextRef context, PGPASN_CONTEXT *asnctx,
		   PGPASN_Certificate *cert, PGPByte loversion,
		   PGPByte *sigBuf, PGPSize *sigLength)
{
	PGPSize certlen;
	PGPSize siglen;
	PGPSize extralen;
	PGPSize certlenlen;
	PGPSize validitylen;
	PGPSize siglevellen;
	PGPSize keyusagelen;
	PGPUInt32 o;
	PGPPublicKeyAlgorithm sigalg;
	PGPHashAlgorithm hashalg;
	PGPError err = kPGPError_NoErr;

	pgpAssert( IsntNull( sigLength ) );
	if( IsNull( sigBuf ) )
		*sigLength = 0;

	/* Get length of validity info */
	err = sDecodeValidity (asnctx, cert, NULL, &validitylen);
	if (IsPGPError(err))
		goto error;

	/* Get length of signing-level info */
	err = sDecodeSigLevel (context, asnctx, cert, NULL, &siglevellen);
	if (IsPGPError(err))
		goto error;

	/* Get length of key-usage info */
	err = sDecodeKeyUsage (asnctx, cert, NULL, &keyusagelen);
	if (IsPGPError(err))
		goto error;

	/* Decode signature algorithm and hash algorithm */
	err = sDecodeAlgorithmOID (asnctx, &cert->signatureAlgorithm.algorithm,
							   &sigalg, &hashalg);
	if( IsPGPError(err) )
		goto error;


	/* Calculate length of signature */
	certlen = pgpasn_SizeofCertificate( asnctx, cert, TRUE ) + 4;
	certlenlen = (certlen < 192) ? 1 : 2;
	extralen = validitylen + siglevellen + keyusagelen
				+ certlen + certlenlen;
	siglen = 8 + extralen + 2 + 3;

	if( IsNull( sigBuf ) ) {
		*sigLength = siglen;
		return kPGPError_NoErr;
	}

	pgpAssert (*sigLength = siglen);

	/* Lay out signature packet */
	
	o = 0;
	sigBuf[o++] = PGPVERSION_4;
	sigBuf[o++] = PGP_SIGTYPE_KEY_GENERIC;
	if (loversion <= 3)
		sigBuf[o++] = 0;		/* Use sigalgorithm of 0 because nonstandard */
	else
		sigBuf[o++] = 100;		/* 100 is more compatible with OpenPGP */
	sigBuf[o++] = hashalg;	/* But use true hash algorithm */

	sigBuf[o++] = (PGPByte) (extralen >> 8);
	sigBuf[o++] = (PGPByte) (extralen >> 0);
	err = sDecodeValidity (asnctx, cert, sigBuf + o, &validitylen);
	o += validitylen;
	err = sDecodeSigLevel (context, asnctx, cert, sigBuf + o, &siglevellen);
	o += siglevellen;
	err = sDecodeKeyUsage (asnctx, cert, sigBuf + o, &keyusagelen);
	o += keyusagelen;

	if (certlenlen == 1)
		sigBuf[o++] = certlen;
	else {
		sigBuf[o++] = (PGPByte) (192 + ((certlen-192) >> 8));
		sigBuf[o++] = (PGPByte) (certlen-192);
	}
	sigBuf[o++] = SIGSUB_NAI;
	sigBuf[o++] = SIGSUBSUB_X509;
	/* Store translation version bytes */
	sigBuf[o++] = SIGSUBSUB_X509_VERSION_HI;
	sigBuf[o++] = loversion;
	pgpasn_PackCertificate( asnctx, sigBuf+o, certlen-4, cert, &err );
	CHKASNERR( err );
	o += certlen - 4;

	/* No non-hashed data (yet) */
	sigBuf[o++] = 0;
	sigBuf[o++] = 0;

	/* End up with dummy 2-byte checksum and dummy MPI for old parsers */
	sigBuf[o++] = 0;
	sigBuf[o++] = 0;
	sigBuf[o++] = 0;
	sigBuf[o++] = 1;
	sigBuf[o++] = 1;

	pgpAssert (o == siglen);

error:
	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 versions uses long form for X509 names, in RFC2253 format.
 */
static PGPError

⌨️ 快捷键说明

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