cms_env.c

来自「openssl」· C语言 代码 · 共 826 行 · 第 1/2 页

C
826
字号
/* For now hard code AES key wrap info */static size_t aes_wrap_keylen(int nid)	{	switch (nid)		{		case NID_id_aes128_wrap:		return 16;		case NID_id_aes192_wrap:		return  24;		case NID_id_aes256_wrap:		return  32;		default:		return 0;		}	}CMS_RecipientInfo *CMS_add0_recipient_key(CMS_ContentInfo *cms, int nid,					unsigned char *key, size_t keylen,					unsigned char *id, size_t idlen,					ASN1_GENERALIZEDTIME *date,					ASN1_OBJECT *otherTypeId,					ASN1_TYPE *otherType)	{	CMS_RecipientInfo *ri = NULL;	CMS_EnvelopedData *env;	CMS_KEKRecipientInfo *kekri;	env = cms_get0_enveloped(cms);	if (!env)		goto err;	if (nid == NID_undef)		{		switch (keylen)			{			case 16:			nid = NID_id_aes128_wrap;			break;			case  24:			nid = NID_id_aes192_wrap;			break;			case  32:			nid = NID_id_aes256_wrap;			break;			default:			CMSerr(CMS_F_CMS_ADD0_RECIPIENT_KEY,						CMS_R_INVALID_KEY_LENGTH);			goto err;			}		}	else		{		size_t exp_keylen = aes_wrap_keylen(nid);		if (!exp_keylen)			{			CMSerr(CMS_F_CMS_ADD0_RECIPIENT_KEY,					CMS_R_UNSUPPORTED_KEK_ALGORITHM);			goto err;			}		if (keylen != exp_keylen)			{			CMSerr(CMS_F_CMS_ADD0_RECIPIENT_KEY,					CMS_R_INVALID_KEY_LENGTH);			goto err;			}		}	/* Initialize recipient info */	ri = M_ASN1_new_of(CMS_RecipientInfo);	if (!ri)		goto merr;	ri->d.kekri = M_ASN1_new_of(CMS_KEKRecipientInfo);	if (!ri->d.kekri)		goto merr;	ri->type = CMS_RECIPINFO_KEK;	kekri = ri->d.kekri;	if (otherTypeId)		{		kekri->kekid->other = M_ASN1_new_of(CMS_OtherKeyAttribute);		if (kekri->kekid->other == NULL)			goto merr;		}	if (!sk_CMS_RecipientInfo_push(env->recipientInfos, ri))		goto merr;	/* After this point no calls can fail */	kekri->version = 4;	kekri->key = key;	kekri->keylen = keylen;	ASN1_STRING_set0(kekri->kekid->keyIdentifier, id, idlen);	kekri->kekid->date = date;	if (kekri->kekid->other)		{		kekri->kekid->other->keyAttrId = otherTypeId;		kekri->kekid->other->keyAttr = otherType;		}	X509_ALGOR_set0(kekri->keyEncryptionAlgorithm,				OBJ_nid2obj(nid), V_ASN1_UNDEF, NULL);	return ri;	merr:	CMSerr(CMS_F_CMS_ADD0_RECIPIENT_KEY, ERR_R_MALLOC_FAILURE);	err:	if (ri)		M_ASN1_free_of(ri, CMS_RecipientInfo);	return NULL;	}int CMS_RecipientInfo_kekri_get0_id(CMS_RecipientInfo *ri,					X509_ALGOR **palg,					ASN1_OCTET_STRING **pid,					ASN1_GENERALIZEDTIME **pdate,					ASN1_OBJECT **potherid,					ASN1_TYPE **pothertype)	{	CMS_KEKIdentifier *rkid;	if (ri->type != CMS_RECIPINFO_KEK)		{		CMSerr(CMS_F_CMS_RECIPIENTINFO_KEKRI_GET0_ID, CMS_R_NOT_KEK);		return 0;		}	rkid =  ri->d.kekri->kekid;	if (palg)		*palg = ri->d.kekri->keyEncryptionAlgorithm;	if (pid)		*pid = rkid->keyIdentifier;	if (pdate)		*pdate = rkid->date;	if (potherid)		{		if (rkid->other)			*potherid = rkid->other->keyAttrId;		else			*potherid = NULL;		}	if (pothertype)		{		if (rkid->other)			*pothertype = rkid->other->keyAttr;		else			*pothertype = NULL;		}	return 1;	}int CMS_RecipientInfo_set0_key(CMS_RecipientInfo *ri, 				unsigned char *key, size_t keylen)	{	CMS_KEKRecipientInfo *kekri;	if (ri->type != CMS_RECIPINFO_KEK)		{		CMSerr(CMS_F_CMS_RECIPIENTINFO_SET0_KEY, CMS_R_NOT_KEK);		return 0;		}	kekri = ri->d.kekri;	kekri->key = key;	kekri->keylen = keylen;	return 1;	}/* Encrypt content key in KEK recipient info */static int cms_RecipientInfo_kekri_encrypt(CMS_ContentInfo *cms,					CMS_RecipientInfo *ri)	{	CMS_EncryptedContentInfo *ec;	CMS_KEKRecipientInfo *kekri;	AES_KEY actx;	unsigned char *wkey = NULL;	int wkeylen;	int r = 0;	ec = cms->d.envelopedData->encryptedContentInfo;	kekri = ri->d.kekri;	if (!kekri->key)		{		CMSerr(CMS_F_CMS_RECIPIENTINFO_KEKRI_ENCRYPT, CMS_R_NO_KEY);		return 0;		}	if (AES_set_encrypt_key(kekri->key, kekri->keylen << 3, &actx))		{ 		CMSerr(CMS_F_CMS_RECIPIENTINFO_KEKRI_ENCRYPT,						CMS_R_ERROR_SETTING_KEY);		goto err;		}	wkey = OPENSSL_malloc(ec->keylen + 8);	if (!wkey)		{ 		CMSerr(CMS_F_CMS_RECIPIENTINFO_KEKRI_ENCRYPT,						ERR_R_MALLOC_FAILURE);		goto err;		}	wkeylen = AES_wrap_key(&actx, NULL, wkey, ec->key, ec->keylen);	if (wkeylen <= 0)		{		CMSerr(CMS_F_CMS_RECIPIENTINFO_KEKRI_ENCRYPT, CMS_R_WRAP_ERROR);		goto err;		}	ASN1_STRING_set0(kekri->encryptedKey, wkey, wkeylen);	r = 1;	err:	if (!r && wkey)		OPENSSL_free(wkey);	OPENSSL_cleanse(&actx, sizeof(actx));	return r;	}/* Decrypt content key in KEK recipient info */static int cms_RecipientInfo_kekri_decrypt(CMS_ContentInfo *cms,					CMS_RecipientInfo *ri)	{	CMS_EncryptedContentInfo *ec;	CMS_KEKRecipientInfo *kekri;	AES_KEY actx;	unsigned char *ukey = NULL;	int ukeylen;	int r = 0, wrap_nid;	ec = cms->d.envelopedData->encryptedContentInfo;	kekri = ri->d.kekri;	if (!kekri->key)		{		CMSerr(CMS_F_CMS_RECIPIENTINFO_KEKRI_DECRYPT, CMS_R_NO_KEY);		return 0;		}	wrap_nid = OBJ_obj2nid(kekri->keyEncryptionAlgorithm->algorithm);	if (aes_wrap_keylen(wrap_nid) != kekri->keylen)		{		CMSerr(CMS_F_CMS_RECIPIENTINFO_KEKRI_DECRYPT,			CMS_R_INVALID_KEY_LENGTH);		return 0;		}	/* If encrypted key length is invalid don't bother */	if (kekri->encryptedKey->length < 16)		{ 		CMSerr(CMS_F_CMS_RECIPIENTINFO_KEKRI_DECRYPT,					CMS_R_INVALID_ENCRYPTED_KEY_LENGTH);		goto err;		}	if (AES_set_decrypt_key(kekri->key, kekri->keylen << 3, &actx))		{ 		CMSerr(CMS_F_CMS_RECIPIENTINFO_KEKRI_DECRYPT,						CMS_R_ERROR_SETTING_KEY);		goto err;		}	ukey = OPENSSL_malloc(kekri->encryptedKey->length - 8);	if (!ukey)		{ 		CMSerr(CMS_F_CMS_RECIPIENTINFO_KEKRI_DECRYPT,						ERR_R_MALLOC_FAILURE);		goto err;		}	ukeylen = AES_unwrap_key(&actx, NULL, ukey,					kekri->encryptedKey->data,					kekri->encryptedKey->length);	if (ukeylen <= 0)		{		CMSerr(CMS_F_CMS_RECIPIENTINFO_KEKRI_DECRYPT,							CMS_R_UNWRAP_ERROR);		goto err;		}	ec->key = ukey;	ec->keylen = ukeylen;	r = 1;	err:	if (!r && ukey)		OPENSSL_free(ukey);	OPENSSL_cleanse(&actx, sizeof(actx));	return r;	}int CMS_RecipientInfo_decrypt(CMS_ContentInfo *cms, CMS_RecipientInfo *ri)	{	switch(ri->type)		{		case CMS_RECIPINFO_TRANS:		return cms_RecipientInfo_ktri_decrypt(cms, ri);		case CMS_RECIPINFO_KEK:		return cms_RecipientInfo_kekri_decrypt(cms, ri);		default:		CMSerr(CMS_F_CMS_RECIPIENTINFO_DECRYPT,			CMS_R_UNSUPPORTED_RECPIENTINFO_TYPE);		return 0;		}	}BIO *cms_EnvelopedData_init_bio(CMS_ContentInfo *cms)	{	CMS_EncryptedContentInfo *ec;	STACK_OF(CMS_RecipientInfo) *rinfos;	CMS_RecipientInfo *ri;	int i, r, ok = 0;	BIO *ret;	/* Get BIO first to set up key */	ec = cms->d.envelopedData->encryptedContentInfo;	ret = cms_EncryptedContent_init_bio(ec);	/* If error or no cipher end of processing */	if (!ret || !ec->cipher)		return ret;	/* Now encrypt content key according to each RecipientInfo type */	rinfos = cms->d.envelopedData->recipientInfos;	for (i = 0; i < sk_CMS_RecipientInfo_num(rinfos); i++)		{		ri = sk_CMS_RecipientInfo_value(rinfos, i);		switch (ri->type)			{			case CMS_RECIPINFO_TRANS:			r = cms_RecipientInfo_ktri_encrypt(cms, ri);			break;			case CMS_RECIPINFO_KEK:			r = cms_RecipientInfo_kekri_encrypt(cms, ri);			break;			default:			CMSerr(CMS_F_CMS_ENVELOPEDDATA_INIT_BIO,				CMS_R_UNSUPPORTED_RECIPIENT_TYPE);			goto err;			}		if (r <= 0)			{			CMSerr(CMS_F_CMS_ENVELOPEDDATA_INIT_BIO,				CMS_R_ERROR_SETTING_RECIPIENTINFO);			goto err;			}		}	ok = 1;	err:	ec->cipher = NULL;	if (ec->key)		{		OPENSSL_cleanse(ec->key, ec->keylen);		OPENSSL_free(ec->key);		ec->key = NULL;		ec->keylen = 0;		}	if (ok)		return ret;	BIO_free(ret);	return NULL;	}

⌨️ 快捷键说明

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