p7common.c

来自「支持SSL v2/v3, TLS, PKCS #5, PKCS #7, PKCS」· C语言 代码 · 共 739 行 · 第 1/2 页

C
739
字号
/* * The contents of this file are subject to the Mozilla Public * License Version 1.1 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.mozilla.org/MPL/ *  * Software distributed under the License is distributed on an "AS * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or * implied. See the License for the specific language governing * rights and limitations under the License. *  * The Original Code is the Netscape security libraries. *  * The Initial Developer of the Original Code is Netscape * Communications Corporation.  Portions created by Netscape are  * Copyright (C) 1994-2000 Netscape Communications Corporation.  All * Rights Reserved. *  * Contributor(s): *  * Alternatively, the contents of this file may be used under the * terms of the GNU General Public License Version 2 or later (the * "GPL"), in which case the provisions of the GPL are applicable  * instead of those above.  If you wish to allow use of your  * version of this file only under the terms of the GPL and not to * allow others to use your version of this file under the MPL, * indicate your decision by deleting the provisions above and * replace them with the notice and other provisions required by * the GPL.  If you do not delete the provisions above, a recipient * may use your version of this file under either the MPL or the * GPL. *//* * PKCS7 implementation -- the exported parts that are used whether * creating or decoding. * * $Id: p7common.c,v 1.1 2000/03/31 19:16:04 relyea%netscape.com Exp $ */#include "p7local.h"#include "cert.h"#include "secitem.h"#include "secoid.h"#include "secpkcs5.h"#include "pk11func.h"/* * Find out (saving pointer to lookup result for future reference) * and return the inner content type. */SECOidTagSEC_PKCS7ContentType (SEC_PKCS7ContentInfo *cinfo){    if (cinfo->contentTypeTag == NULL)	cinfo->contentTypeTag = SECOID_FindOID(&(cinfo->contentType));    if (cinfo->contentTypeTag == NULL)	return SEC_OID_UNKNOWN;    return cinfo->contentTypeTag->offset;}/* * Destroy a PKCS7 contentInfo and all of its sub-pieces. */voidSEC_PKCS7DestroyContentInfo(SEC_PKCS7ContentInfo *cinfo){    SECOidTag kind;    CERTCertificate **certs;    CERTCertificateList **certlists;    SEC_PKCS7SignerInfo **signerinfos;    SEC_PKCS7RecipientInfo **recipientinfos;    PORT_Assert (cinfo->refCount > 0);    if (cinfo->refCount <= 0)	return;    cinfo->refCount--;    if (cinfo->refCount > 0)	return;    certs = NULL;    certlists = NULL;    recipientinfos = NULL;    signerinfos = NULL;    kind = SEC_PKCS7ContentType (cinfo);    switch (kind) {      case SEC_OID_PKCS7_ENVELOPED_DATA:	{	    SEC_PKCS7EnvelopedData *edp;	    edp = cinfo->content.envelopedData;	    if (edp != NULL) {		recipientinfos = edp->recipientInfos;	    }	}	break;      case SEC_OID_PKCS7_SIGNED_DATA:	{	    SEC_PKCS7SignedData *sdp;	    sdp = cinfo->content.signedData;	    if (sdp != NULL) {		certs = sdp->certs;		certlists = sdp->certLists;		signerinfos = sdp->signerInfos;	    }	}	break;      case SEC_OID_PKCS7_SIGNED_ENVELOPED_DATA:	{	    SEC_PKCS7SignedAndEnvelopedData *saedp;	    saedp = cinfo->content.signedAndEnvelopedData;	    if (saedp != NULL) {		certs = saedp->certs;		certlists = saedp->certLists;		recipientinfos = saedp->recipientInfos;		signerinfos = saedp->signerInfos;		if (saedp->sigKey != NULL)		    PK11_FreeSymKey (saedp->sigKey);	    }	}	break;      default:	/* XXX Anything else that needs to be "manually" freed/destroyed? */	break;    }    if (certs != NULL) {	CERTCertificate *cert;	while ((cert = *certs++) != NULL) {	    CERT_DestroyCertificate (cert);	}    }    if (certlists != NULL) {	CERTCertificateList *certlist;	while ((certlist = *certlists++) != NULL) {	    CERT_DestroyCertificateList (certlist);	}    }    if (recipientinfos != NULL) {	SEC_PKCS7RecipientInfo *ri;	while ((ri = *recipientinfos++) != NULL) {	    if (ri->cert != NULL)		CERT_DestroyCertificate (ri->cert);	}    }    if (signerinfos != NULL) {	SEC_PKCS7SignerInfo *si;	while ((si = *signerinfos++) != NULL) {	    if (si->cert != NULL)		CERT_DestroyCertificate (si->cert);	    if (si->certList != NULL)		CERT_DestroyCertificateList (si->certList);	}    }    if (cinfo->poolp != NULL) {	PORT_FreeArena (cinfo->poolp, PR_FALSE);	/* XXX clear it? */    }}/* * Return a copy of the given contentInfo.  The copy may be virtual * or may be real -- either way, the result needs to be passed to * SEC_PKCS7DestroyContentInfo later (as does the original). */SEC_PKCS7ContentInfo *SEC_PKCS7CopyContentInfo(SEC_PKCS7ContentInfo *cinfo){    if (cinfo == NULL)	return NULL;    PORT_Assert (cinfo->refCount > 0);    if (cinfo->created) {	/*	 * Want to do a real copy of these; otherwise subsequent	 * changes made to either copy are likely to be a surprise.	 * XXX I suspect that this will not actually be called for yet,	 * which is why the assert, so to notice if it is...	 */	PORT_Assert (0);	/*	 * XXX Create a new pool here, and copy everything from	 * within.  For cert stuff, need to call the appropriate	 * copy functions, etc.	 */    }    cinfo->refCount++;    return cinfo;}/* * Return a pointer to the actual content.  In the case of those types * which are encrypted, this returns the *plain* content. * XXX Needs revisiting if/when we handle nested encrypted types. */SECItem *SEC_PKCS7GetContent(SEC_PKCS7ContentInfo *cinfo){    SECOidTag kind;    kind = SEC_PKCS7ContentType (cinfo);    switch (kind) {      case SEC_OID_PKCS7_DATA:	return cinfo->content.data;      case SEC_OID_PKCS7_DIGESTED_DATA:	{	    SEC_PKCS7DigestedData *digd;	    digd = cinfo->content.digestedData;	    if (digd == NULL)		break;	    return SEC_PKCS7GetContent (&(digd->contentInfo));	}      case SEC_OID_PKCS7_ENCRYPTED_DATA:	{	    SEC_PKCS7EncryptedData *encd;	    encd = cinfo->content.encryptedData;	    if (encd == NULL)		break;	    return &(encd->encContentInfo.plainContent);	}      case SEC_OID_PKCS7_ENVELOPED_DATA:	{	    SEC_PKCS7EnvelopedData *envd;	    envd = cinfo->content.envelopedData;	    if (envd == NULL)		break;	    return &(envd->encContentInfo.plainContent);	}      case SEC_OID_PKCS7_SIGNED_DATA:	{	    SEC_PKCS7SignedData *sigd;	    sigd = cinfo->content.signedData;	    if (sigd == NULL)		break;	    return SEC_PKCS7GetContent (&(sigd->contentInfo));	}      case SEC_OID_PKCS7_SIGNED_ENVELOPED_DATA:	{	    SEC_PKCS7SignedAndEnvelopedData *saed;	    saed = cinfo->content.signedAndEnvelopedData;	    if (saed == NULL)		break;	    return &(saed->encContentInfo.plainContent);	}      default:	PORT_Assert(0);	break;    }    return NULL;}/* * XXX Fix the placement and formatting of the * following routines (i.e. make them consistent with the rest of * the pkcs7 code -- I think some/many belong in other files and * they all need a formatting/style rehaul) *//* retrieve the algorithm identifier for encrypted data.   * the identifier returned is a copy of the algorithm identifier * in the content info and needs to be freed after being used. * *   cinfo is the content info for which to retrieve the *     encryption algorithm. * * if the content info is not encrypted data or an error  * occurs NULL is returned. */SECAlgorithmID *SEC_PKCS7GetEncryptionAlgorithm(SEC_PKCS7ContentInfo *cinfo){  SECAlgorithmID *alg = 0;  switch (SEC_PKCS7ContentType(cinfo))    {    case SEC_OID_PKCS7_ENCRYPTED_DATA:      alg = &cinfo->content.encryptedData->encContentInfo.contentEncAlg;      break;    case SEC_OID_PKCS7_ENVELOPED_DATA:      alg = &cinfo->content.envelopedData->encContentInfo.contentEncAlg;      break;    case SEC_OID_PKCS7_SIGNED_ENVELOPED_DATA:      alg = &cinfo->content.signedAndEnvelopedData	->encContentInfo.contentEncAlg;      break;    default:      alg = 0;      break;    }    return alg;}/* set the content of the content info.  For data content infos, * the data is set.  For encrytped content infos, the plainContent * is set, and is expected to be encrypted later. *   * cinfo is the content info where the data will be set * * buf is a buffer of the data to set * * len is the length of the data being set. * * in the event of an error, SECFailure is returned.  SECSuccess  * indicates the content was successfully set. */SECStatus SEC_PKCS7SetContent(SEC_PKCS7ContentInfo *cinfo,		    const char *buf, 		    unsigned long len){    SECOidTag cinfo_type;    SECStatus rv;    SECItem content;    SECOidData *contentTypeTag = NULL;    content.data = (unsigned char *)buf;    content.len = len;    cinfo_type = SEC_PKCS7ContentType(cinfo);    /* set inner content */    switch(cinfo_type)    {	case SEC_OID_PKCS7_SIGNED_DATA:	    if(content.len > 0) {		/* we "leak" the old content here, but as it's all in the pool */		/* it does not really matter */		/* create content item if necessary */		if (cinfo->content.signedData->contentInfo.content.data == NULL)		    cinfo->content.signedData->contentInfo.content.data = SECITEM_AllocItem(cinfo->poolp, NULL, 0);		rv = SECITEM_CopyItem(cinfo->poolp, 			cinfo->content.signedData->contentInfo.content.data,			&content);	    } else {		cinfo->content.signedData->contentInfo.content.data->data = NULL;		cinfo->content.signedData->contentInfo.content.data->len = 0;		rv = SECSuccess;	    }	    if(rv == SECFailure)		goto loser;	    	    break;	case SEC_OID_PKCS7_ENCRYPTED_DATA:

⌨️ 快捷键说明

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