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

📄 pgpx509keys.c

📁 vc环境下的pgp源码
💻 C
📖 第 1 页 / 共 5 页
字号:
}


/*
 * Convert an RFC2253 LDAP-format string to an allocated Distinguished
 * Name buffer.  Caller should do PGPFreeData on *pdname when done.  Any
 * quoting used in input must be double quotes around the whole value,
 * as in O="Network Associates, Inc.".
 */
	PGPError
PGPCreateDistinguishedName( PGPContextRef context, char const *str,
	PGPByte **pdname)
{
	PGPMemoryMgrRef mgr;
	PGPASN_CONTEXT  asnctx_static, *asnctx = &asnctx_static;
	PGPASN_MemoryMgr asnmem;
	PGPASN_Name *name = NULL;
	PGPByte *dname = NULL;
	PGPSize dnamesize;
	PGPError err = kPGPError_NoErr;

	*pdname = NULL;

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

	err = sEncodeDN( mgr, asnctx, str, &name );
	if( IsPGPError( err ) )
		goto error;

	dnamesize = pgpasn_SizeofName (asnctx, name, TRUE);
	dname = PGPNewData( mgr, dnamesize, 0 );
	CHKNONNULL( dname, err );
	pgpasn_PackName( asnctx, dname, dnamesize, name, &err );
	CHKASNERR( err );

	pgpasn_FreeName( asnctx, name );

	*pdname = dname;
	return kPGPError_NoErr;

 error:
	if( name )
		pgpasn_FreeName( asnctx, name );
	if( dname )
		PGPFreeData( dname );
	return err;
}

#endif

	
/*
 * Add backslashes as needed for X.509 LDAP format conversion
 * Allocate s2 to be twice as big as s1, for safety.
 */
	static void
sEncodeLDAPString( const char *s1, char *s2 )
{
	PGPBoolean inQuotes = FALSE;
	PGPBoolean afterBackslash = FALSE;
	char c;

	while ((c = *s1++) != '\0') {
		if (c == '"' && !afterBackslash)
			inQuotes = !inQuotes;
		if (inQuotes) {
			if (c == '=' || c == '\\' || c == ',' || c == '+' ||
				c == '<' || c == '>' || c == ';' || c == ' ' || c == '#')
				*s2++ = '\\';
		}
		if (((c != '\\' || !inQuotes) && c != '"') || afterBackslash)
			*s2++ = c;
		afterBackslash = (c == '\\' && !afterBackslash);
	}
	*s2++ = '\0';
}

/*
 * Convert an RFC2253 LDAP-format string to an allocated Distinguished
 * Name buffer.  Caller should do PGPFreeData on *pdname when done.
 */
	PGPError
PGPCreateDistinguishedName( PGPContextRef context, char const *str,
	PGPByte **pdname, PGPSize *pdnamelen )
{
	PGPByte *dname = NULL;
	PGPSize dnamelen;
	char *str2 = NULL;
	PGPError err = kPGPError_NoErr;
	PGPMemoryMgrRef mgr = PGPGetContextMemoryMgr( context );

	PGPValidatePtr( pdname );
	PGPValidatePtr( pdnamelen );

	*pdname = NULL;
	*pdnamelen = 0;

	str2 = (char *)PGPNewData( mgr, 2*strlen(str) + 1, 0 );
	CHKNONNULL( str2, err );
	sEncodeLDAPString( str, str2 );

	err = X509CreateDistinguishedName( context, str2, &dname, &dnamelen );

	if( IsPGPError( err ) )
		goto error;

	*pdname = dname;
	*pdnamelen = dnamelen;

 error:
	if( IsPGPError( err ) && IsntNull(dname) )
		PGPFreeData( dname );
	if( str2 )
		PGPFreeData( str2 );
	return err;
}



/*
 * Given an X509 integer (pointing past the tag/length), return a PGP
 * format MPI number.  If the mpbuf pointer is NULL, just return the len.
 * If non-NULL, *mplen must equal the required length.
 */
static PGPError
sDecodeX509Integer (PGPByte const *buf, PGPSize len,
		PGPByte *mpbuf, PGPSize *mplen)
{
	PGPUInt32 bits;
	
	/* Skip past any zero padding */
	while (*buf == '\0' && len > 0) {
		++buf;
		--len;
	}
	
	/* Must be at least 1 byte long */
	if (len == 0)
		return kPGPError_X509InvalidCertificateFormat;

	/* Set MPI with bitcount prefix */
	if( IsNull( mpbuf ) ) {
		*mplen = len + 2;
		return kPGPError_NoErr;
	}

	pgpAssert (len + 2 == *mplen);
		
	bits = (len-1) * 8 + hibit(*buf) + 1;
	mpbuf[0] = (PGPByte)(bits >> 8);
	mpbuf[1] = (PGPByte)(bits >> 0);
	pgpCopyMemory( buf, mpbuf+2, len);

	return kPGPError_NoErr;
}


/*
 * Decode the given UTCTime buffer into a standard PGP timestamp
 * If generalized is true, it is a GeneralizedTime structure, four digit
 * years.
 */
static PGPError
sDecodeUTCTime (PGPByte const *buf, PGPSize len, PGPBoolean generalized,
				PGPUInt32 *timestamp)
{
	PGPUInt32 datefield[6];		/* year, month, day, hour, min, second */
	PGPUInt32 i;
	PGPUInt32 tstamp;
	PGPError err = kPGPError_NoErr;

	pgpAssert( IsntNull( timestamp ) );
	*timestamp = 0;

	pgpClearMemory (datefield, sizeof(datefield));

	for (i=0; i<elemsof(datefield); ++i) {
		if (len < 2 || !isdigit(buf[0]))
			break;
		if (!isdigit(buf[1])) {
			err = kPGPError_X509InvalidCertificateFormat;
			goto error;
		}
		datefield[i] = (buf[0]-'0') * 10 + (buf[1] - '0');
		buf += 2;
		len -= 2;
		if (i == 0 && generalized) {
			/* Two more digits */
			datefield[i] = datefield[i] * 100 + (buf[0]-'0') * 10
							+ (buf[1] - '0');
			buf += 2;
			len -= 2;
		}
	}
	if (len != 1  ||  buf[0] != 'Z'  ||  i < 5) {
		err = kPGPError_X509InvalidCertificateFormat;
		goto error;
	}
	
	/* Correct for Y2K conventions on UTCTime */
	if (!generalized)
		datefield[0] += (datefield[0] > 50) ? 1900 : 2000;

	/* Get seconds since Jan 1, 1970 */
	tstamp = pgpDateFromYMD (datefield[0], datefield[1], datefield[2]);
	tstamp = (((tstamp*24 + datefield[3]) * 60) + datefield[4]) * 60
		+ datefield[5];

	*timestamp = tstamp;

error:

	return err;
}



/* 
 * TRUE if given DN string needs quoting per RFC1779.
 * Also return the number of internal backslashes needed.
 */
static PGPBoolean
sNeedsDNQuoting(PGPByte const *buf, PGPSize length, PGPUInt32 *nslashes)
{
	PGPByte c='\0', prevc='\0';
	PGPUInt32 nslash = 0;
	PGPBoolean outerquote = FALSE;

	if (*buf==' ')
		outerquote = TRUE;
	while (length--) {
		prevc = c;
		c = *buf++;
		if (c==',' || c=='=' || c=='\r' || c=='+' || c=='<'
			|| c=='>' || c=='#' || c==';')
			outerquote = TRUE;
		if (c==' ' && prevc==' ')
			outerquote = TRUE;
		if (c=='"' || c=='\\')
			++nslash;
	}
	if (prevc==' ')
		outerquote = TRUE;
	if (IsntNull (nslashes) )
		*nslashes = nslash;
	return outerquote;
}


/*
 * If out is non-NULL, apply RFC1779 DNS quoting to buf, outputting to out.
 * In either case, return the length of what the output string would be.
 * If the rev flag is set, out points at the end of the output buffer rather
 * than at the beginning.
 */
static PGPUInt32
sDNQuoteString(PGPByte const *buf, PGPSize len, PGPByte *out, PGPBoolean rev)
{
	PGPUInt32 outlen;
	PGPBoolean needouterquote;
	PGPByte c;

	needouterquote = sNeedsDNQuoting( buf, len, &outlen);
	outlen += len + (needouterquote ? 2 : 0);
	if (IsNull( out ))
		return outlen;
	if (rev)
		out -= outlen;
	if (needouterquote)
		*out++ = '"';
	while (len--) {
		c = *buf++;
		if (c=='"' || c=='\\')
			*out++ = '\\';
		*out++ = c;
	}
	if (needouterquote)
		*out++ = '"';
	return outlen;
}


/*
 * Called pointing at the OID for an algorithm identifier, see if it is one
 * we know.
 */
static PGPError
sDecodeAlgorithmOID (PGPASN_CONTEXT *asnctx, PGPASN_OBJECT_ID *oid,
	PGPPublicKeyAlgorithm *keyalgorithm, PGPHashAlgorithm *hashalgorithm)
{
	PGPByte *buf = oid->val;
	PGPSize len = oid->len;
	PGPError err = kPGPError_NoErr;

	(void) asnctx;

	if( IsntNull( keyalgorithm ) )
		*keyalgorithm = (PGPPublicKeyAlgorithm) 0;

	if( IsntNull( hashalgorithm ) )
		*hashalgorithm = (PGPHashAlgorithm) 0;

	if (len == sizeof(rsaoid) && memcmp (buf, rsaoid, len) == 0) {
		if( IsntNull( keyalgorithm ) )
			*keyalgorithm = kPGPPublicKeyAlgorithm_RSA;
	} else if (len == sizeof(rsamd5oid) && memcmp (buf, rsamd5oid, len) == 0) {
		if( IsntNull( hashalgorithm ) )
			*hashalgorithm = kPGPHashAlgorithm_MD5;
		if( IsntNull( keyalgorithm ) )
			*keyalgorithm = kPGPPublicKeyAlgorithm_RSA;
	} else if (len == sizeof(rsamd2oid) && memcmp (buf, rsamd2oid, len) == 0) {
		if( IsntNull( hashalgorithm ) )
			*hashalgorithm = (PGPHashAlgorithm) kPGPHashAlgorithm_MD2;
		if( IsntNull( keyalgorithm ) )
			*keyalgorithm = kPGPPublicKeyAlgorithm_RSA;
	} else if (len == sizeof(rsashaoid) && memcmp (buf, rsashaoid, len) == 0) {
		if( IsntNull( hashalgorithm ) )
			*hashalgorithm = (PGPHashAlgorithm) kPGPHashAlgorithm_SHA;
		if( IsntNull( keyalgorithm ) )
			*keyalgorithm = kPGPPublicKeyAlgorithm_RSA;
	} else if (len == sizeof(dsaoid) && memcmp (buf, dsaoid, len) == 0) {
		if( IsntNull( keyalgorithm ) )
			*keyalgorithm = kPGPPublicKeyAlgorithm_DSA;
	} else if ((len == sizeof(dsashaoid1) && memcmp (buf,dsashaoid1,len) == 0)
		  || (len == sizeof(dsashaoid2) && memcmp (buf,dsashaoid2,len) == 0)) {
		if( IsntNull( hashalgorithm ) )
			*hashalgorithm = kPGPHashAlgorithm_SHA;
		if( IsntNull( keyalgorithm ) )
			*keyalgorithm = kPGPPublicKeyAlgorithm_DSA;
	} else if (len == sizeof(elgoid) && memcmp (buf, elgoid, len) == 0) {
		if( IsntNull( keyalgorithm ) )
			*keyalgorithm = kPGPPublicKeyAlgorithm_ElGamal;
	} else {
		err = kPGPError_X509InvalidCertificateFormat;
	}
	return err;
}


/*
 * Look for IP address or DNS name in subject alternative name extension
 * If ipbuf is NULL, set *iplength to necessary length; else store the
 * IP data into ipbuf, and treat *iplength as an input parameter telling
 * what the length needs to be.  (Presumably *iplength is always 4?)
 * If dnsbuf is NULL, set *dnslength to necessary length; else store the
 * DNS name into dnsbuf, and treat *dnslength as an input parameter telling
 * what the length needs to be.
 * If there is more than one IP or DNS we just return the first of each
 * type.
 */
static PGPError
sDecodeIPDNSName(PGPASN_CONTEXT *asnctx, PGPASN_Certificate *cert,
				 PGPByte *ipbuf, PGPSize *iplength,
				 PGPByte *dnsbuf, PGPSize *dnslength)
{
	PGPASN_Extensions *exts;
	PGPASN_Extension *ext;
	PGPASN_GeneralNames *gnames;
	PGPASN_GeneralName *gname;
	PGPASN_VariableBlock *vb;
	PGPBoolean seenIP=FALSE, seenDNS=FALSE;
	PGPInt32 i, j;
	PGPError err = kPGPError_NoErr;

	if (IsNull( ipbuf ) && IsntNull( iplength ) )
		*iplength = 0;
	if (IsNull( dnsbuf ) && IsntNull( dnslength ) )
		*dnslength = 0;

	exts = cert->tbsCertificate.extensions;
	if (IsNull(exts))
		return err;

	/* Check extensions for subject alternative name */
	for (i=0; i<exts->n && (!seenIP || !seenDNS); ++i) {
		ext = exts->elt[i];
		/* These are same size */
		if (ext->extnID.len == sizeof(subaltnameoid)
			&& memcmp(ext->extnID.val, subaltnameoid, ext->extnID.len)==0 ) {
			/* Subject alternative name, just as we wanted */
			pgpasn_UnpackGeneralNames( asnctx, &gnames, ext->extnValue.val,
									   ext->extnValue.len, &err );
			if (err != 0) {
				/* Skip if can't handle */
				err = 0;
				continue;
			}
			for (j=0; j<gnames->n && (!seenIP || !seenDNS); ++j) {
				gname = gnames->elt[j];
				if (gname->CHOICE_field_type == ASN_GENERALNAME_IPADDRESS
					&& !seenIP) {
					seenIP = TRUE;
					vb = gname->data;
					if (IsNull( ipbuf ) ) {
						if( IsntNull( iplength ) )
							*iplength = vb->len;
					} else {
						pgpCopyMemory( vb->val, ipbuf, vb->len );
					}
				} else if (gname->CHOICE_field_type == ASN_GENERALNAME_DNSNAME
						   && !seenDNS) {
					seenDNS = TRUE;
					vb = gname->data;
					if (IsNull( dnsbuf ) ) {
						if( IsntNull( dnslength ) )
							*dnslength = vb->len;
					} else {
						pgpCopyMemory( vb->val, dnsbuf, vb->len );
					}
				}
			}
			pgpasn_FreeGeneralNames( asnctx, gnames );
		}
	}
	return err;
}


/*
 * Convert from X.509 cert to PGP signature validity subpackets.
 * If vbuf is NULL, set *vlength to the necessary length.  Else
 * store the data into vbuf, and treat *vlength as an input parameter
 * telling what the length needs to be.
 * We create a pair of PGP signature subpackets expressing creation and
 * expiration dates.
 */
static PGPError
sDecodeValidity(PGPASN_CONTEXT *asnctx, PGPASN_Certificate *cert,
				PGPByte *vbuf, PGPSize *vlength)
{
	PGPASN_Validity *val = &cert->tbsCertificate.validity;
	PGPASN_CertificateValidityDate *cvd;
	PGPASN_UTCTime *utc;
	PGPUInt32 creationtime;
	PGPUInt32 expirationtime;
	PGPUInt32 o;
	PGPError err = kPGPError_NoErr;

	(void)asnctx;
	pgpAssert( IsntNull( vlength ) );

	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;

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

	if (expirationtime < creationtime) {
		err = kPGPError_X509InvalidCertificateFormat;
		goto error;
	}
	expirationtime -= creationtime;

	/* Two subpackets, each with 1 byte of len, 1 byte of type, 4 of time */
	if( IsNull( vbuf ) ) {
		*vlength = 2 * 6;
		return kPGPError_NoErr;
	}

	pgpAssert (*vlength == 2 * 6);

	o = 0;

⌨️ 快捷键说明

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