cms_env.c

来自「OpenSSL 0.9.8k 最新版OpenSSL」· C语言 代码 · 共 826 行 · 第 1/2 页

C
826
字号
/* crypto/cms/cms_env.c *//* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL * project. *//* ==================================================================== * Copyright (c) 2008 The OpenSSL Project.  All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer.  * * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in *    the documentation and/or other materials provided with the *    distribution. * * 3. All advertising materials mentioning features or use of this *    software must display the following acknowledgment: *    "This product includes software developed by the OpenSSL Project *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" * * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to *    endorse or promote products derived from this software without *    prior written permission. For written permission, please contact *    licensing@OpenSSL.org. * * 5. Products derived from this software may not be called "OpenSSL" *    nor may "OpenSSL" appear in their names without prior written *    permission of the OpenSSL Project. * * 6. Redistributions of any form whatsoever must retain the following *    acknowledgment: *    "This product includes software developed by the OpenSSL Project *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" * * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. * ==================================================================== */#include "cryptlib.h"#include <openssl/asn1t.h>#include <openssl/pem.h>#include <openssl/x509v3.h>#include <openssl/err.h>#include <openssl/cms.h>#include <openssl/rand.h>#include <openssl/aes.h>#include "cms_lcl.h"/* CMS EnvelopedData Utilities */DECLARE_ASN1_ITEM(CMS_EnvelopedData)DECLARE_ASN1_ITEM(CMS_RecipientInfo)DECLARE_ASN1_ITEM(CMS_KeyTransRecipientInfo)DECLARE_ASN1_ITEM(CMS_KEKRecipientInfo)DECLARE_ASN1_ITEM(CMS_OtherKeyAttribute)DECLARE_STACK_OF(CMS_RecipientInfo)static CMS_EnvelopedData *cms_get0_enveloped(CMS_ContentInfo *cms)	{	if (OBJ_obj2nid(cms->contentType) != NID_pkcs7_enveloped)		{		CMSerr(CMS_F_CMS_GET0_ENVELOPED,				CMS_R_CONTENT_TYPE_NOT_ENVELOPED_DATA);		return NULL;		}	return cms->d.envelopedData;	}static CMS_EnvelopedData *cms_enveloped_data_init(CMS_ContentInfo *cms)	{	if (cms->d.other == NULL)		{		cms->d.envelopedData = M_ASN1_new_of(CMS_EnvelopedData);		if (!cms->d.envelopedData)			{			CMSerr(CMS_F_CMS_ENVELOPED_DATA_INIT,							ERR_R_MALLOC_FAILURE);			return NULL;			}		cms->d.envelopedData->version = 0;		cms->d.envelopedData->encryptedContentInfo->contentType =						OBJ_nid2obj(NID_pkcs7_data);		ASN1_OBJECT_free(cms->contentType);		cms->contentType = OBJ_nid2obj(NID_pkcs7_enveloped);		return cms->d.envelopedData;		}	return cms_get0_enveloped(cms);	}STACK_OF(CMS_RecipientInfo) *CMS_get0_RecipientInfos(CMS_ContentInfo *cms)	{	CMS_EnvelopedData *env;	env = cms_get0_enveloped(cms);	if (!env)		return NULL;	return env->recipientInfos;	}int CMS_RecipientInfo_type(CMS_RecipientInfo *ri)	{	return ri->type;	}CMS_ContentInfo *CMS_EnvelopedData_create(const EVP_CIPHER *cipher)	{	CMS_ContentInfo *cms;	CMS_EnvelopedData *env;	cms = CMS_ContentInfo_new();	if (!cms)		goto merr;	env = cms_enveloped_data_init(cms);	if (!env)		goto merr;	if (!cms_EncryptedContent_init(env->encryptedContentInfo,					cipher, NULL, 0))		goto merr;	return cms;	merr:	if (cms)		CMS_ContentInfo_free(cms);	CMSerr(CMS_F_CMS_ENVELOPEDDATA_CREATE, ERR_R_MALLOC_FAILURE);	return NULL;	}/* Key Transport Recipient Info (KTRI) routines *//* Add a recipient certificate. For now only handle key transport. * If we ever handle key agreement will need updating. */CMS_RecipientInfo *CMS_add1_recipient_cert(CMS_ContentInfo *cms,					X509 *recip, unsigned int flags)	{	CMS_RecipientInfo *ri = NULL;	CMS_KeyTransRecipientInfo *ktri;	CMS_EnvelopedData *env;	EVP_PKEY *pk = NULL;	int type;	env = cms_get0_enveloped(cms);	if (!env)		goto err;	/* Initialize recipient info */	ri = M_ASN1_new_of(CMS_RecipientInfo);	if (!ri)		goto merr;	/* Initialize and add key transport recipient info */	ri->d.ktri = M_ASN1_new_of(CMS_KeyTransRecipientInfo);	if (!ri->d.ktri)		goto merr;	ri->type = CMS_RECIPINFO_TRANS;	ktri = ri->d.ktri;	X509_check_purpose(recip, -1, -1);	pk = X509_get_pubkey(recip);	if (!pk)		{		CMSerr(CMS_F_CMS_ADD1_RECIPIENT_CERT,				CMS_R_ERROR_GETTING_PUBLIC_KEY);		goto err;		}	CRYPTO_add(&recip->references, 1, CRYPTO_LOCK_X509);	ktri->pkey = pk;	ktri->recip = recip;	if (flags & CMS_USE_KEYID)		{		ktri->version = 2;		type = CMS_RECIPINFO_KEYIDENTIFIER;		}	else		{		ktri->version = 0;		type = CMS_RECIPINFO_ISSUER_SERIAL;		}	/* Not a typo: RecipientIdentifier and SignerIdentifier are the	 * same structure.	 */	if (!cms_set1_SignerIdentifier(ktri->rid, recip, type))		goto err;	/* Since we have no EVP_PKEY_ASN1_METHOD in OpenSSL 0.9.8,	 * hard code algorithm parameters.	 */	if (pk->type == EVP_PKEY_RSA)		{		X509_ALGOR_set0(ktri->keyEncryptionAlgorithm,					OBJ_nid2obj(NID_rsaEncryption), 					V_ASN1_NULL, 0);		}	else		{		CMSerr(CMS_F_CMS_ADD1_RECIPIENT_CERT,				CMS_R_NOT_SUPPORTED_FOR_THIS_KEY_TYPE);		goto err;		}	if (!sk_CMS_RecipientInfo_push(env->recipientInfos, ri))		goto merr;	return ri;	merr:	CMSerr(CMS_F_CMS_ADD1_RECIPIENT_CERT, ERR_R_MALLOC_FAILURE);	err:	if (ri)		M_ASN1_free_of(ri, CMS_RecipientInfo);	return NULL;	}int CMS_RecipientInfo_ktri_get0_algs(CMS_RecipientInfo *ri,					EVP_PKEY **pk, X509 **recip,					X509_ALGOR **palg)	{	CMS_KeyTransRecipientInfo *ktri;	if (ri->type != CMS_RECIPINFO_TRANS)		{		CMSerr(CMS_F_CMS_RECIPIENTINFO_KTRI_GET0_ALGS,			CMS_R_NOT_KEY_TRANSPORT);		return 0;		}	ktri = ri->d.ktri;	if (pk)		*pk = ktri->pkey;	if (recip)		*recip = ktri->recip;	if (palg)		*palg = ktri->keyEncryptionAlgorithm;	return 1;	}int CMS_RecipientInfo_ktri_get0_signer_id(CMS_RecipientInfo *ri,					ASN1_OCTET_STRING **keyid,					X509_NAME **issuer, ASN1_INTEGER **sno)	{	CMS_KeyTransRecipientInfo *ktri;	if (ri->type != CMS_RECIPINFO_TRANS)		{		CMSerr(CMS_F_CMS_RECIPIENTINFO_KTRI_GET0_SIGNER_ID,			CMS_R_NOT_KEY_TRANSPORT);		return 0;		}	ktri = ri->d.ktri;	return cms_SignerIdentifier_get0_signer_id(ktri->rid,							keyid, issuer, sno);	}int CMS_RecipientInfo_ktri_cert_cmp(CMS_RecipientInfo *ri, X509 *cert)	{	if (ri->type != CMS_RECIPINFO_TRANS)		{		CMSerr(CMS_F_CMS_RECIPIENTINFO_KTRI_CERT_CMP,			CMS_R_NOT_KEY_TRANSPORT);		return -2;		}	return cms_SignerIdentifier_cert_cmp(ri->d.ktri->rid, cert);	}int CMS_RecipientInfo_set0_pkey(CMS_RecipientInfo *ri, EVP_PKEY *pkey)	{	if (ri->type != CMS_RECIPINFO_TRANS)		{		CMSerr(CMS_F_CMS_RECIPIENTINFO_SET0_PKEY,			CMS_R_NOT_KEY_TRANSPORT);		return 0;		}	ri->d.ktri->pkey = pkey;	return 1;	}/* Encrypt content key in key transport recipient info */static int cms_RecipientInfo_ktri_encrypt(CMS_ContentInfo *cms,					CMS_RecipientInfo *ri)	{	CMS_KeyTransRecipientInfo *ktri;	CMS_EncryptedContentInfo *ec;	unsigned char *ek = NULL;	int eklen;	int ret = 0;	if (ri->type != CMS_RECIPINFO_TRANS)		{		CMSerr(CMS_F_CMS_RECIPIENTINFO_KTRI_ENCRYPT,			CMS_R_NOT_KEY_TRANSPORT);		return 0;		}	ktri = ri->d.ktri;	ec = cms->d.envelopedData->encryptedContentInfo;	eklen = EVP_PKEY_size(ktri->pkey);	ek = OPENSSL_malloc(eklen);	if (ek == NULL)		{		CMSerr(CMS_F_CMS_RECIPIENTINFO_KTRI_ENCRYPT,							ERR_R_MALLOC_FAILURE);		goto err;		}	eklen = EVP_PKEY_encrypt(ek, ec->key, ec->keylen, ktri->pkey);	if (eklen <= 0)		goto err;	ASN1_STRING_set0(ktri->encryptedKey, ek, eklen);	ek = NULL;	ret = 1;	err:	if (ek)		OPENSSL_free(ek);	return ret;	}/* Decrypt content key from KTRI */static int cms_RecipientInfo_ktri_decrypt(CMS_ContentInfo *cms,							CMS_RecipientInfo *ri)	{	CMS_KeyTransRecipientInfo *ktri = ri->d.ktri;	unsigned char *ek = NULL;	int eklen;	int ret = 0;	if (ktri->pkey == NULL)		{		CMSerr(CMS_F_CMS_RECIPIENTINFO_KTRI_DECRYPT,			CMS_R_NO_PRIVATE_KEY);		return 0;		}	eklen = EVP_PKEY_size(ktri->pkey);	ek = OPENSSL_malloc(eklen);	if (ek == NULL)		{		CMSerr(CMS_F_CMS_RECIPIENTINFO_KTRI_DECRYPT,							ERR_R_MALLOC_FAILURE);		goto err;		}	eklen = EVP_PKEY_decrypt(ek, 				ktri->encryptedKey->data,				ktri->encryptedKey->length, ktri->pkey);	if (eklen <= 0)		{		CMSerr(CMS_F_CMS_RECIPIENTINFO_KTRI_DECRYPT, CMS_R_CMS_LIB);		goto err;		}	ret = 1;	cms->d.envelopedData->encryptedContentInfo->key = ek;	cms->d.envelopedData->encryptedContentInfo->keylen = eklen;	err:	if (!ret && ek)		OPENSSL_free(ek);	return ret;	}/* Key Encrypted Key (KEK) RecipientInfo routines */int CMS_RecipientInfo_kekri_id_cmp(CMS_RecipientInfo *ri, 					const unsigned char *id, size_t idlen)	{	ASN1_OCTET_STRING tmp_os;	CMS_KEKRecipientInfo *kekri;	if (ri->type != CMS_RECIPINFO_KEK)		{		CMSerr(CMS_F_CMS_RECIPIENTINFO_KEKRI_ID_CMP, CMS_R_NOT_KEK);		return -2;		}	kekri = ri->d.kekri;	tmp_os.type = V_ASN1_OCTET_STRING;	tmp_os.flags = 0;	tmp_os.data = (unsigned char *)id;	tmp_os.length = (int)idlen;	return ASN1_OCTET_STRING_cmp(&tmp_os, kekri->kekid->keyIdentifier);	}

⌨️ 快捷键说明

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