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

📄 x509inputcertificate.c

📁 可以实现对邮件的加密解密以及签名
💻 C
📖 第 1 页 / 共 2 页
字号:
{
	/* The calling function expects to be returned SET OF Certificate, but
	   the PKCS-7 definition ExtendedCertificatesAndCertificates produces the
	   same encoding when no ExtendedCertificate's are present, so just use
	   that defintion to reduce code size */
	PKIExtendedCertificatesAndCertificates	*certSet = NULL;

	PKICONTEXT					asnContext;
	PKIContentInfo				*contentInfo = NULL;
	PKISignedData				*sigData = NULL;
	PKIEnvelopedData			*envData = NULL;
	PKICertificateRevocationLists		*crls = NULL;
	PGPError					err;
	PGPMemoryMgrRef				mem = PGPPeekContextMemoryMgr (context);
	PGPByte					*contentData = NULL;
	PGPSize					contentDataLen;
	int						messageType;
	int						asnError = 0;

	(void) passphrase;	/* Unused argument */
	(void) format;	/* Unused argument */

	/* clear outputs */
	*sigPresent = 0;
	*sigChecked = 0;
	*sigVerified = 0;
	*extraData = NULL;
	*extraDataCount = 0;
	*decryptKey = NULL;
	*signKey = NULL;
	*crlOut = NULL;
	*crlOutSize = 0;

	memset (&asnContext, 0, sizeof (PKICONTEXT));
	asnContext.memMgr = &X509CMSMemoryMgr;
	asnContext.memMgr->customValue = (void *) mem;

	certSet = PKINewExtendedCertificatesAndCertificates (&asnContext);
	crls = PKINewCertificateRevocationLists(&asnContext);

	/* first check to see if input is a plain x.509 certificate.  if not, check
	   to see if input is a plain CRL.  failing that, attempt to decode as
	   a PKCS-7 message */
	if (x509ParseAsCertificate(&asnContext,input,inputSize,certSet)!=kPGPError_NoErr &&
		x509ParseAsCRL(&asnContext,input,inputSize,crls)!=kPGPError_NoErr)
	{
		/* either this is not a certificate/crl or it has a bad encoding, so
		   try to decode it as a PKCS-7 message */

		contentInfo = sm_DecodeMessage (input, inputSize, &asnContext);
		if (!contentInfo)
		{
			/* failed to decode message */
			err = kPGPError_InvalidPKCS7Encoding;
			goto error_exit;
		}

		messageType = sm_MessageType (contentInfo, &asnContext);
		if (!contentInfo->content)
		{
			PKIFreeContentInfo (&asnContext, contentInfo);
			err = kPGPError_InvalidPKCS7Encoding;
			goto error_exit;
		}

		/* save the internal content */
		contentData = contentInfo->content->val;
		contentDataLen = contentInfo->content->len;

		contentInfo->content->val = NULL;
		contentInfo->content->len = 0;
		PGPFreeData (contentInfo->content);
		contentInfo->content = NULL;

		PKIFreeContentInfo (&asnContext, contentInfo);

		/* remove the security enhancements */
		while (messageType == PKCS7_CONTENT_SIGNED_DATA ||
			messageType == PKCS7_CONTENT_ENVELOPED_DATA)
		{
			if (messageType == PKCS7_CONTENT_SIGNED_DATA)
			{
				sigData = sm_DecodeSignedData (contentData,
					contentDataLen,
					&asnContext);
				if (!sigData)
				{
					err = kPGPError_InvalidPKCS7Encoding; /* parse error */
					goto error_exit;
				}

				/* find our key based on the transaction-id in the
				   authenticated attributes */
				if (!*decryptKey)
				{
					*decryptKey = x509FindPrivateKey (context, keydb,
						&asnContext, &sigData->signerInfos);
				}

				/* check for signature.  since the returned certificate is
				   itself signed, we don't exit upon failure during this
				   step */
				x509VerifyPKCS7Signatures (
					context,
					keydb,
					&asnContext,
					sigData,
					sigPresent,
					sigChecked,
					sigVerified,
					signKey);

				/* if there are certificates present, return them */
				x509ExtractCertificatesFromSignedData (&asnContext, sigData,
													   certSet);

				/* if there are CRLs present, return them */
				x509ExtractCRLsFromSignedData (&asnContext, sigData, crls);

				PGPFreeData (contentData); /* free existing data */

				/* get the content data */
				sm_VerifyMessage (&contentData,
					&contentDataLen,
					sigData,
					NULL,
					NULL,
					NULL,
					NULL,
					NULL,
					&asnContext);

				/* peek at the internal content type */
				messageType = sm_ContentType (&sigData->contentInfo.contentType, &asnContext);

				PKIFreeSignedData (&asnContext, sigData);
				sigData = NULL;
			}
			else
			{
				/* EnvelopedData */

				X509CMSCallbackData	pgpData;

				pgpAssert (messageType == PKCS7_CONTENT_ENVELOPED_DATA);

				envData = sm_DecodeEnvelopedData (contentData, contentDataLen,
					&asnContext);
				if (!envData)
				{
					err = kPGPError_InvalidPKCS7Encoding;
					goto error_exit;
				}

				PGPFreeData (contentData);
				contentData = 0;

				memset (&pgpData, 0, sizeof (pgpData));
				pgpData.passphrase = passphrase;
				pgpData.context = context;
				pgpData.key = *decryptKey; /* my private key */

				if (sm_DecryptMessage (&contentData,
						&contentDataLen,
						envData,
						NULL, /* use first recipient */
						pkcs7DecryptCallback,
						(void *) &pgpData,
						&asnContext) != PKCS7_OK)
				{
					err = kPGPError_PKCS7DecryptFailure;
					goto error_exit;
				}

				/* peek at the internal content type */
				messageType = sm_ContentType (&envData->encryptedContentInfo.contentType,
					&asnContext);

				PKIFreeEnvelopedData (&asnContext, envData);
				envData = NULL;
			}

			/* Netscape CMS 4.1 also encrypts the message, so do a quick
			   check to see if this look like an encrypted message.  we do
			   this by looking to see if this looks like the beginning of
			   an ASN.1 SEQUENCE OF */
			if (messageType == PKCS7_CONTENT_DATA &&
				contentDataLen && *contentData == 0x30)
			{
				/* probably ASN.1 */
				contentInfo = sm_DecodeMessage (contentData, contentDataLen,
					&asnContext);
				if (contentInfo)
				{
					/* yes, it really is */

					/* set the correct message type */
					messageType = sm_MessageType (contentInfo, &asnContext);

					/* replace the current content with the interior content */
					PGPFreeData (contentData);
					if (contentInfo->content)
					{
						contentData = contentInfo->content->val;
						contentDataLen = contentInfo->content->len;

						/* so PKIFreeContentInfo doesn't free the memory */
						PGPFreeData (contentInfo->content);
						contentInfo->content = NULL;
					}
					else
					{
						contentData = NULL;
						contentDataLen = 0;
					}

					PKIFreeContentInfo (&asnContext, contentInfo);
				}
			}
		}

		if (messageType != PKCS7_CONTENT_DATA)
		{
			/* unknown PKCS7 content type */
			err = kPGPError_InvalidPKCS7Encoding;
			goto error_exit;
		}

		/* if we have something from Verisign, the certificates are located
		   in the body of the signed message */
		if (contentData)
		{
			PKICertRep *certRep;

			/* Try to parse with VeriSign structure (extra reginfo) */
			asnError = 0;
			PKIUnpackCertRep (&asnContext,
				&certRep,
				contentData,
				contentDataLen,
				&asnError);

			if (certRep) {
				/* Verisign parse succeeded, extract contentInfo portion */
				contentInfo = certRep->certs;
				certRep->certs = NULL;
				PKIFreeCertRep (&asnContext, certRep);
			} else {
				/* Try to parse as a plain CMS message */
				asnError = 0;
				contentInfo = sm_DecodeMessage (contentData, contentDataLen,
												&asnContext);
			}

			if (contentInfo)
			{
				messageType = sm_MessageType (contentInfo, &asnContext);
				if (messageType == PKCS7_CONTENT_SIGNED_DATA &&
					contentInfo->content)
				{
					PKIUnpackSignedData (&asnContext, &sigData,
										 contentInfo->content->val,
										 contentInfo->content->len,
										 &asnError);
					if (!asnError)
					{
						x509ExtractCertificatesFromSignedData (&asnContext,
															   sigData,
															   certSet);
						x509ExtractCRLsFromSignedData (&asnContext, sigData,
													   crls);
						PKIFreeSignedData (&asnContext, sigData);
						sigData = NULL;
					}
				}
				PKIFreeContentInfo (&asnContext, contentInfo);
			}
		}
	}

	asnError = 0; /* reset error code */

	if (certSet->n)
	{
		*certOutSize = PKISizeofExtendedCertificatesAndCertificates (
			&asnContext,
			certSet,
			1);
		*certOut = PGPNewData (mem, *certOutSize, 0);
		asnError = 0;
		PKIPackExtendedCertificatesAndCertificates (&asnContext,
			*certOut,
			*certOutSize,
			certSet,
			&asnError);
		if (asnError)
		{
			PGPFreeData (*certOut);
			*certOut = NULL;
			*certOutSize = 0;
			err = kPGPError_ASNPackFailure;
			goto error_exit;
		}
	}

	if (crls->n)
	{
		/* if we found CRLs, pack them up now */
		*crlOutSize = PKISizeofCertificateRevocationLists (&asnContext, crls, 1);
		*crlOut = PGPNewData (mem, *crlOutSize, 0);
		PKIPackCertificateRevocationLists (&asnContext, *crlOut, *crlOutSize, crls, &asnError);
		if (asnError)
		{
			PGPFreeData (*crlOut);
			*crlOut = NULL;
			*crlOutSize = 0;

			PGPFreeData (*certOut);
			*certOut = NULL;
			*certOutSize = 0;

			err = kPGPError_ASNPackFailure;
			goto error_exit;
		}
	}

	err = kPGPError_NoErr;

error_exit:

	/* certSet and crls should always have been allocated */
	PKIFreeExtendedCertificatesAndCertificates (&asnContext, certSet);
	PKIFreeCertificateRevocationLists(&asnContext, crls);

	if (envData)
		PKIFreeEnvelopedData (&asnContext, envData);
	if (sigData)
		PKIFreeSignedData (&asnContext, sigData);
	if (contentData)
		PGPFreeData (contentData);
	if (passphrase)
		PGPFreeOptionList (passphrase);

	return err;
}

/* vim:ts=4:sw=4:
 */

⌨️ 快捷键说明

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