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

📄 x509packagecertificaterequest.c

📁 可以实现对邮件的加密解密以及签名
💻 C
📖 第 1 页 / 共 2 页
字号:
		memset (&pgpData, 0, sizeof (pgpData));
		pgpData.passphrase = passphrase;
		pgpData.context = context;

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

		/*	if encryption is requested, we do it BEFORE signing per the
			CRS/CEP spec */

		/* NOTE: the Netscape CA requires us to generate an EnvelopedData
			object encapsulated inside of a ContentInfo, which is then
			labeled as Data and put inside a SignedData object.  This is
			different from what you would normally do with PKCS-7.  Apparently
			Cisco shipped an early product that did it this way and to be
			backwards compatible they never changed it to do it the correct
			way.  So we have to make sure not to label the EnvelopedData
			as nested, and always use Data as the internal content type for
			the outer SignedData object
			-michael 11/24/99 */

		if (encryptTo)
		{
			PGPByte				*cert;
			PGPSize				certLength;
			EncryptRecipient	recipEntry;
			List				recipientCertificates;
			/* since only Netscape requires encryption, we hard code the
				the algorithm here */
			const char *encryptAlgString = SM_OID_ALG_DES;	/* DES-CBC */

			memset (&recipientCertificates, 0, sizeof (List));
			recipientCertificates.data = (void *) &recipEntry;

			memset (&recipEntry, 0, sizeof (recipEntry));
			recipEntry.data = (void *) encryptTo;

			/* get the certificate associated with this key */
			err = PGPExport (context,
				PGPOExportKeyDBObj (context, encryptTo),
				PGPOAllocatedOutputBuffer (context, (void **) &cert, 4096, &certLength),
				PGPOExportFormat (pgpData.context, kPGPExportFormat_X509Cert),
				PGPOLastOption (pgpData.context));
			if (IsPGPError (err))
				goto error_exit;

			PKIUnpackCertificate (&asnContext, &recipEntry.certificate,
				cert, certLength, &asnError);

			PGPFreeData (cert);

			if (asnError)
			{
				/* unable to unpack certificate */
				err = kPGPError_X509CertificateParseError;
				goto error_exit;
			}

			result = sm_EncryptMessage (certReqOut,
				certReqOutSize,
				certReqIn,
				certReqInSize,
				0, /* not nested, generate a envelopedData with ContentInfo */
				SM_OID_CONTENT_DATA,
				encryptAlgString,
				&recipientCertificates,
				pkcs7EncryptCallback,
				(void *) &pgpData,
				&asnContext);

			PKIFreeCertificate (&asnContext, recipEntry.certificate);

			if (result != PKCS7_OK)
			{
				err = kPGPError_PKCS7EncryptFailure;
				goto error_exit;
			}

			inputData = *certReqOut;
			inputDataSize = *certReqOutSize;
		}

		/* we always require a signature */
		pgpAssert (signWith != 0);

		if (signWith)
		{
			/* algs hard hardcoded for now */
			const char	*digestAlgString;
			const char	*signatureAlgString;
			PGPInt32	keyAlgID;
			char		rsaSigParam[2] = { 0x05, 0x00 };
			char		*sigParam = NULL;
			size_t		sigParamSize = 0;
			char		md5param[2] = { 0x05, 0x00 };
			char		*digestParam = NULL;
			size_t		digestParamSize = 0;

			PKIINTEGER	*type;
			PKIOCTET_STRING	*nonce;
			PGPByte		*val;
			PGPSize		i, len;

			pgpData.key = signWith;

			/* determine pub key algorithm */
			err = PGPGetKeyDBObjNumericProperty (signWith, kPGPKeyProperty_AlgorithmID, &keyAlgID);
			if (IsPGPError (err))
				goto error_exit;
			switch (keyAlgID)
			{
				case kPGPPublicKeyAlgorithm_DSA:
					digestAlgString = SM_OID_ALG_SHA;
					signatureAlgString = SM_OID_ALG_DSA;
					break;
				case kPGPPublicKeyAlgorithm_RSA:
				case kPGPPublicKeyAlgorithm_RSASignOnly:
				case kPGPPublicKeyAlgorithm_RSAEncryptOnly:
					digestAlgString = SM_OID_ALG_MD5;
					signatureAlgString = SM_OID_ALG_RSA;
					/* VeriSign requires the parameters for the digestAlg
					   and sigAlg to be explicitly encoded as ASN.1 NULL
					   rather than be omitted */
					sigParam = rsaSigParam;
					sigParamSize = sizeof rsaSigParam;
					digestParam = md5param;
					digestParamSize = sizeof md5param;
					break;
				default:
					err = kPGPError_UnknownPublicKeyAlgorithm;
					goto error_exit;
			}

			/* no certificate for this key, assume we need to generate
			   a temporary self-signed certificate for this message,
			   as prescribed by the VeriSign CRS specification */

			/* if this is a PKCSReq message, use the information in the
			   PKCS-10 request as the basis for the DN for the self-signed
			   cert.  otherwise generate a simple certificate. */
			err = x509CreateSelfSignedCertificate (signWith,
				&asnContext,
				&pgpData,
				isCertReq ? certReqIn : NULL,
				isCertReq ? certReqInSize : 0,
				format,
				&sigCert);
			if (IsPGPError (err))
				goto error_exit;

			pgpAssert (sigCert != 0);

			if( sigCert )
			{
				includeCerts = PGPNewData (mem, sizeof (List),
										   kPGPMemoryMgrFlags_Clear);
				if (!includeCerts)
				{
					err = kPGPError_OutOfMemory;
					goto error_exit;
				}
				includeCerts->data = (void *) sigCert;
			}

			/* ----- begin building up the pkcs-7 message ----- */

			attr = PKINewAttributes (&asnContext);

			/* add the message-type attribute */
			type = PKINewINTEGER (&asnContext);
			
			if (isCertReq)
				msgtype = 19;
			else if (isGetCertInitial)
				msgtype = 20;
			else
				msgtype = 22; /* GetCRL */

			/* Entrust and Netscape use PrintableString, others use INTEGER */
			if (isEntrust || isNetscape || isMicrosoft)
			{
				char str[3];
				
				i=0;
				if(msgtype>10)
					str[i++]=msgtype/10+'0';
				str[i++]=msgtype%10+'0';
				str[i]=0;
				PKIPutStrVal(&asnContext, type, str);
				len=PKISizeofPrintableString(&asnContext, type, 1);
				val=PGPNewData(mem,len,0);
				if(!val) {
					err=kPGPError_OutOfMemory;
					goto error_exit;
				}
				PKIPackPrintableString(&asnContext, val, len, type, &asnError);
				PKIFreePrintableString(&asnContext, type);
			} else {
				PKIPutIntVal (&asnContext, type, msgtype);
				len = PKISizeofINTEGER (&asnContext, type, 1);
				val = PGPNewData (mem, len, 0);
				PKIPackINTEGER (&asnContext, val, len, type, &asnError);
			    PKIFreeINTEGER (&asnContext, type);
			}
			if (asnError)
				err = kPGPError_ASNPackFailure;

			if (IsPGPError (err)) {
				PGPFreeData (val);
				goto error_exit;
			}

			err = x509AddAuthAttribute (&asnContext,
				PKIat_pki_message_type_OID,
				PKIat_pki_message_type_OID_LEN,
				val,
				len,
				attr);

			PGPFreeData (val);

			if (IsPGPError (err))
				goto error_exit;

			/* add the sendernonce attribute */
			nonce = PKINewOCTET_STRING (&asnContext);
			nonce->len = 16;
			nonce->val = PGPNewData (mem, nonce->len, 0);
			err = PGPContextGetRandomBytes (context,
				nonce->val,
				nonce->len);
			if (IsPGPError (err))
			{
				PKIFreeOCTET_STRING (&asnContext, nonce);
				goto error_exit;
			}
			len = PKISizeofOCTET_STRING (&asnContext, nonce, 1);
			val = PGPNewData (mem, len, 0);
			PKIPackOCTET_STRING (&asnContext, val, len, nonce, &asnError);
			PKIFreeOCTET_STRING (&asnContext, nonce);
			if (!asnError)
				err = x509AddAuthAttribute (&asnContext,
					PKIat_pki_sendernonce_OID,
					PKIat_pki_sendernonce_OID_LEN,
					val,
					len,
					attr);
			else
				err = kPGPError_ASNPackFailure;

			PGPFreeData (val);

			if (IsPGPError (err))
				goto error_exit;

			/* add the transactionid attribute */
			if( transIDSize > 0 )
			{
				/* User caller-supplied transaction ID */
				val = transIDIn;
				len = transIDSize;
			} else {
				/* Calculate trans ID as hash of public key */
				err = x509HashPublicKey (context, &asnContext,
					&sigCert->tbsCertificate.subjectPublicKeyInfo,
					&val,
					&len);
				if (IsPGPError (err))
					goto error_exit;
			}

			type = PKINewINTEGER (&asnContext);

			/* Entrust and Netscape use PrintableString, others use INTEGER */
			if (isEntrust || isNetscape || isMicrosoft)
			{
#if 1
				type->len=len*2;
				type->val=PGPNewData(mem, type->len + 1, 0);
				for(i=0;(unsigned)i<len;i++)
					sprintf((char *)(type->val + (2 * i)), "%2.2X", (unsigned int) val[i]);
#else
				/* fake transaction id for testing purposes */
				type->len = 2;
				type->val = PGPNewData (mem, type->len, 0);
				memcpy (type->val, "42", type->len);
#endif
				if( transIDSize == 0 )
					PGPFreeData (val);

				len = PKISizeofPrintableString (&asnContext, type, 1);
				val = PGPNewData (mem, len, 0);
				PKIPackPrintableString (&asnContext, val, len, type, &asnError);
				PKIFreePrintableString (&asnContext, type);
			}
			else
			{
				PKIPutUIntBytes (&asnContext, type, val, len);
				if( transIDSize == 0 )
					PGPFreeData (val);
				len = PKISizeofINTEGER (&asnContext, type, 1);
				val = PGPNewData (mem, len, 0);
				PKIPackINTEGER (&asnContext, val, len, type, &asnError);
				PKIFreeINTEGER (&asnContext, type);
			}
			if (asnError)
				err = kPGPError_ASNPackFailure;
			if (IsPGPError (err)) {
				PGPFreeData (val);
				goto error_exit;
			}

			err = x509AddAuthAttribute (&asnContext,
				PKIat_pki_transactionid_OID,
				PKIat_pki_transactionid_OID_LEN,
				val,
				len,
				attr);

			PGPFreeData (val);

			if (IsPGPError (err))
				goto error_exit;

			result = sm_SignMessage (certReqOut,
				certReqOutSize,
				inputData,
				inputDataSize,
				0,			/* not nested, outer content type */
				SM_OID_CONTENT_DATA,	/* always Data, even when encrypting (see comment above */
				digestAlgString,
				(uchar *) digestParam,
				digestParamSize,
				signatureAlgString,
				(uchar *) sigParam,
				sigParamSize,
				sigCert,
				attr,		/* signed attributes */
				includeCerts,	/* certs to include in PKCS7 message */
				pkcs7HashCallback,
				(void *) &pgpData,
				pkcs7SignCallback,
				(void *) &pgpData,
				&asnContext);
			if (result != PKCS7_OK)
			{
				err = kPGPError_PKCS7SignFailure;
				goto error_exit;
			}
		}
	}
	else if (format == kPGPOutputFormat_NetToolsCAV1_CertReqInPKCS7) /* jason: what if we ever want */
	{																 /* to create a real PKCS7 cert? */
		/* no extra encoding required, just return what we were given */

		*certReqOutSize = certReqInSize;
		*certReqOut = PGPNewData (PGPPeekContextMemoryMgr (context),
			*certReqOutSize,
			0);
		memcpy (*certReqOut, certReqIn, *certReqOutSize);
	}
	else
		return kPGPError_InvalidOutputFormat;

	err = kPGPError_NoErr;

error_exit:

	if (attr)
		PKIFreeAttributes (&asnContext, attr);
	if (sigCert)
		PKIFreeCertificate (&asnContext, sigCert);
	if (includeCerts)
		PGPFreeData (includeCerts);

	if (inputData != certReqIn)
	{
		/* free intermediate data */
		PKIFree (asnContext.memMgr, inputData);
	}

	if (IsPGPError (err))
	{
		/* clean up allocated data on failure */
		if (*certReqOut)
		{
			if( *certReqOut != inputData )
				PGPFreeData (*certReqOut);
			*certReqOut = NULL;
			*certReqOutSize = 0;
		}
	}

	/* callback functions just make a copy of this since we could possible
	   use it more than once, so free the master copy */
	PGPFreeOptionList (passphrase);

	return (err); /* success */
}

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

⌨️ 快捷键说明

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