Commit eeb9cdfc authored by Dr. Stephen Henson's avatar Dr. Stephen Henson
Browse files

Add support for KEK decrypt in cms utility.

parent 16fe5f8b
Loading
Loading
Loading
Loading
+25 −2
Original line number Diff line number Diff line
@@ -465,7 +465,7 @@ int MAIN(int argc, char **argv)
		}
	else if (operation == SMIME_DECRYPT)
		{
		if (!recipfile && !keyfile)
		if (!recipfile && !keyfile && !secret_key)
			{
			BIO_printf(bio_err, "No recipient certificate or key specified\n");
			badarg = 1;
@@ -838,7 +838,30 @@ int MAIN(int argc, char **argv)
	ret = 4;
	if (operation == SMIME_DECRYPT)
		{
		if (!CMS_decrypt(cms, key, recip, indata, out, flags))

		if (secret_key)
			{
			if (!CMS_decrypt_set1_key(cms,
						secret_key, secret_keylen,
						secret_keyid, secret_keyidlen))
				{
				BIO_puts(bio_err,
					"Error decrypting CMS using secret key\n");
				goto end;
				}
			}

		if (key)
			{
			if (!CMS_decrypt_set1_pkey(cms, key, recip))
				{
				BIO_puts(bio_err,
					"Error decrypting CMS using private key\n");
				goto end;
				}
			}

		if (!CMS_decrypt(cms, NULL, NULL, indata, out, flags))
			{
			BIO_printf(bio_err, "Error decrypting CMS structure\n");
			goto end;
+18 −1
Original line number Diff line number Diff line
@@ -167,6 +167,11 @@ int CMS_decrypt(CMS_ContentInfo *cms, EVP_PKEY *pkey, X509 *cert,
				BIO *data, BIO *dcont,
				unsigned int flags);
	
int CMS_decrypt_set1_pkey(CMS_ContentInfo *cms, EVP_PKEY *pk, X509 *cert);
int CMS_decrypt_set1_key(CMS_ContentInfo *cms, 
				unsigned char *key, size_t keylen,
				unsigned char *id, size_t idlen);

STACK_OF(CMS_RecipientInfo) *CMS_get0_RecipientInfos(CMS_ContentInfo *cms);
int CMS_RecipientInfo_type(CMS_RecipientInfo *ri);
CMS_ContentInfo *CMS_EnvelopedData_create(const EVP_CIPHER *cipher);
@@ -188,6 +193,12 @@ CMS_RecipientInfo *CMS_add0_recipient_key(CMS_ContentInfo *cms, int nid,
					ASN1_OBJECT *otherTypeId,
					ASN1_TYPE *otherType);

int CMS_RecipientInfo_set0_key(CMS_RecipientInfo *ri, 
				unsigned char *key, size_t keylen);

int CMS_RecipientInfo_kekri_id_cmp(CMS_RecipientInfo *ri, 
					const unsigned char *id, size_t idlen);

int CMS_RecipientInfo_decrypt(CMS_ContentInfo *cms, CMS_RecipientInfo *ri);
	
int CMS_uncompress(CMS_ContentInfo *cms, BIO *dcont, BIO *out,
@@ -297,6 +308,8 @@ void ERR_load_CMS_strings(void);
#define CMS_F_CMS_DECRYPT				 152
#define CMS_F_CMS_DECRYPTEDCONTENT_DECRYPT_BIO		 145
#define CMS_F_CMS_DECRYPTEDCONTENT_ENCRYPT_BIO		 143
#define CMS_F_CMS_DECRYPT_SET1_KEY			 167
#define CMS_F_CMS_DECRYPT_SET1_PKEY			 168
#define CMS_F_CMS_DIGESTALGORITHM_FIND_CTX		 110
#define CMS_F_CMS_DIGESTALGORITHM_INIT_BIO		 111
#define CMS_F_CMS_DIGESTEDDATA_DO_FINAL			 112
@@ -322,9 +335,12 @@ void ERR_load_CMS_strings(void);
#define CMS_F_CMS_GET0_REVOCATION_CHOICES		 120
#define CMS_F_CMS_GET0_SIGNED				 121
#define CMS_F_CMS_RECIPIENTINFO_DECRYPT			 150
#define CMS_F_CMS_RECIPIENTINFO_KEKI_KEY_CMP		 164
#define CMS_F_CMS_RECIPIENTINFO_KEKRI_DECRYPT		 161
#define CMS_F_CMS_RECIPIENTINFO_KEKRI_ENCRYPT		 162
#define CMS_F_CMS_RECIPIENTINFO_KEKRI_GET0_ID		 158
#define CMS_F_CMS_RECIPIENTINFO_KEKRI_ID_CMP		 166
#define CMS_F_CMS_RECIPIENTINFO_KEKRI_KEY_CMP		 165
#define CMS_F_CMS_RECIPIENTINFO_KTRI_CERT_CMP		 122
#define CMS_F_CMS_RECIPIENTINFO_KTRI_DECRYPT		 160
#define CMS_F_CMS_RECIPIENTINFO_KTRI_ENCRYPT		 155
@@ -359,6 +375,7 @@ void ERR_load_CMS_strings(void);
#define CMS_R_CONTENT_VERIFY_ERROR			 106
#define CMS_R_CTRL_ERROR				 107
#define CMS_R_CTRL_FAILURE				 108
#define CMS_R_DECRYPT_ERROR				 159
#define CMS_R_ERROR_GETTING_PUBLIC_KEY			 109
#define CMS_R_ERROR_READING_MESSAGEDIGEST_ATTRIBUTE	 110
#define CMS_R_ERROR_SETTING_KEY				 155
+28 −9
Original line number Diff line number Diff line
@@ -431,6 +431,24 @@ static int cms_RecipientInfo_ktri_decrypt(CMS_ContentInfo *cms,

/* 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);
	}

/* For now hard code AES key wrap info */

static size_t aes_wrap_keylen(int nid)
@@ -605,20 +623,13 @@ int CMS_RecipientInfo_set0_key(CMS_RecipientInfo *ri,
				unsigned char *key, size_t keylen)
	{
	CMS_KEKRecipientInfo *kekri;
	int wrap_nid;
	if (ri->type != CMS_RECIPINFO_KEK)
		{
		CMSerr(CMS_F_CMS_RECIPIENTINFO_SET0_KEY, CMS_R_NOT_KEK);
		return 0;
		}

	kekri = ri->d.kekri;
	wrap_nid = OBJ_obj2nid(kekri->keyEncryptionAlgorithm->algorithm);
	if (aes_wrap_keylen(wrap_nid) != keylen)
		{
		CMSerr(CMS_F_CMS_RECIPIENTINFO_SET0_KEY,
			CMS_R_INVALID_KEY_LENGTH);
		return 0;
		}
	kekri->key = key;
	kekri->keylen = keylen;
	return 1;
@@ -695,7 +706,7 @@ static int cms_RecipientInfo_kekri_decrypt(CMS_ContentInfo *cms,
	AES_KEY actx;
	unsigned char *ukey = NULL;
	int ukeylen;
	int r = 0;
	int r = 0, wrap_nid;

	ec = cms->d.envelopedData->encryptedContentInfo;

@@ -707,6 +718,14 @@ static int cms_RecipientInfo_kekri_decrypt(CMS_ContentInfo *cms,
		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)
+8 −2
Original line number Diff line number Diff line
@@ -71,7 +71,7 @@
static ERR_STRING_DATA CMS_str_functs[]=
	{
{ERR_FUNC(CMS_F_CHECK_CONTENT),	"CHECK_CONTENT"},
{ERR_FUNC(CMS_F_CMS_ADD0_RECIPIENT_KEY),	"CMS_ADD0_RECIPIENT_KEY"},
{ERR_FUNC(CMS_F_CMS_ADD0_RECIPIENT_KEY),	"CMS_add0_recipient_key"},
{ERR_FUNC(CMS_F_CMS_ADD1_RECIPIENT_CERT),	"CMS_add1_recipient_cert"},
{ERR_FUNC(CMS_F_CMS_ADD1_SIGNER),	"CMS_add1_signer"},
{ERR_FUNC(CMS_F_CMS_ADD1_SIGNINGTIME),	"CMS_ADD1_SIGNINGTIME"},
@@ -88,6 +88,8 @@ static ERR_STRING_DATA CMS_str_functs[]=
{ERR_FUNC(CMS_F_CMS_DECRYPT),	"CMS_decrypt"},
{ERR_FUNC(CMS_F_CMS_DECRYPTEDCONTENT_DECRYPT_BIO),	"CMS_DECRYPTEDCONTENT_DECRYPT_BIO"},
{ERR_FUNC(CMS_F_CMS_DECRYPTEDCONTENT_ENCRYPT_BIO),	"CMS_DECRYPTEDCONTENT_ENCRYPT_BIO"},
{ERR_FUNC(CMS_F_CMS_DECRYPT_SET1_KEY),	"CMS_DECRYPT_SET1_KEY"},
{ERR_FUNC(CMS_F_CMS_DECRYPT_SET1_PKEY),	"CMS_DECRYPT_SET1_PKEY"},
{ERR_FUNC(CMS_F_CMS_DIGESTALGORITHM_FIND_CTX),	"CMS_DIGESTALGORITHM_FIND_CTX"},
{ERR_FUNC(CMS_F_CMS_DIGESTALGORITHM_INIT_BIO),	"CMS_DIGESTALGORITHM_INIT_BIO"},
{ERR_FUNC(CMS_F_CMS_DIGESTEDDATA_DO_FINAL),	"CMS_DIGESTEDDATA_DO_FINAL"},
@@ -113,15 +115,18 @@ static ERR_STRING_DATA CMS_str_functs[]=
{ERR_FUNC(CMS_F_CMS_GET0_REVOCATION_CHOICES),	"CMS_GET0_REVOCATION_CHOICES"},
{ERR_FUNC(CMS_F_CMS_GET0_SIGNED),	"CMS_GET0_SIGNED"},
{ERR_FUNC(CMS_F_CMS_RECIPIENTINFO_DECRYPT),	"CMS_RecipientInfo_decrypt"},
{ERR_FUNC(CMS_F_CMS_RECIPIENTINFO_KEKI_KEY_CMP),	"CMS_RECIPIENTINFO_KEKI_KEY_CMP"},
{ERR_FUNC(CMS_F_CMS_RECIPIENTINFO_KEKRI_DECRYPT),	"CMS_RECIPIENTINFO_KEKRI_DECRYPT"},
{ERR_FUNC(CMS_F_CMS_RECIPIENTINFO_KEKRI_ENCRYPT),	"CMS_RECIPIENTINFO_KEKRI_ENCRYPT"},
{ERR_FUNC(CMS_F_CMS_RECIPIENTINFO_KEKRI_GET0_ID),	"CMS_RECIPIENTINFO_KEKRI_GET0_ID"},
{ERR_FUNC(CMS_F_CMS_RECIPIENTINFO_KEKRI_ID_CMP),	"CMS_RecipientInfo_kekri_id_cmp"},
{ERR_FUNC(CMS_F_CMS_RECIPIENTINFO_KEKRI_KEY_CMP),	"CMS_RECIPIENTINFO_KEKRI_KEY_CMP"},
{ERR_FUNC(CMS_F_CMS_RECIPIENTINFO_KTRI_CERT_CMP),	"CMS_RecipientInfo_ktri_cert_cmp"},
{ERR_FUNC(CMS_F_CMS_RECIPIENTINFO_KTRI_DECRYPT),	"CMS_RECIPIENTINFO_KTRI_DECRYPT"},
{ERR_FUNC(CMS_F_CMS_RECIPIENTINFO_KTRI_ENCRYPT),	"CMS_RECIPIENTINFO_KTRI_ENCRYPT"},
{ERR_FUNC(CMS_F_CMS_RECIPIENTINFO_KTRI_GET0_ALGS),	"CMS_RecipientInfo_ktri_get0_algs"},
{ERR_FUNC(CMS_F_CMS_RECIPIENTINFO_KTRI_GET0_SIGNER_ID),	"CMS_RecipientInfo_ktri_get0_signer_id"},
{ERR_FUNC(CMS_F_CMS_RECIPIENTINFO_SET0_KEY),	"CMS_RECIPIENTINFO_SET0_KEY"},
{ERR_FUNC(CMS_F_CMS_RECIPIENTINFO_SET0_KEY),	"CMS_RecipientInfo_set0_key"},
{ERR_FUNC(CMS_F_CMS_RECIPIENTINFO_SET0_PKEY),	"CMS_RecipientInfo_set0_pkey"},
{ERR_FUNC(CMS_F_CMS_SET1_SIGNERIDENTIFIER),	"CMS_SET1_SIGNERIDENTIFIER"},
{ERR_FUNC(CMS_F_CMS_SET_DETACHED),	"CMS_set_detached"},
@@ -153,6 +158,7 @@ static ERR_STRING_DATA CMS_str_reasons[]=
{ERR_REASON(CMS_R_CONTENT_VERIFY_ERROR)  ,"content verify error"},
{ERR_REASON(CMS_R_CTRL_ERROR)            ,"ctrl error"},
{ERR_REASON(CMS_R_CTRL_FAILURE)          ,"ctrl failure"},
{ERR_REASON(CMS_R_DECRYPT_ERROR)         ,"decrypt error"},
{ERR_REASON(CMS_R_ERROR_GETTING_PUBLIC_KEY),"error getting public key"},
{ERR_REASON(CMS_R_ERROR_READING_MESSAGEDIGEST_ATTRIBUTE),"error reading messagedigest attribute"},
{ERR_REASON(CMS_R_ERROR_SETTING_KEY)     ,"error setting key"},
+78 −33
Original line number Diff line number Diff line
@@ -494,23 +494,11 @@ CMS_ContentInfo *CMS_encrypt(STACK_OF(X509) *certs, BIO *data,
	return NULL;
	}

int CMS_decrypt(CMS_ContentInfo *cms, EVP_PKEY *pk, X509 *cert,
				BIO *dcont, BIO *out,
				unsigned int flags)
	{
	int i, r;
	BIO *cont;
	if (OBJ_obj2nid(CMS_get0_type(cms)) != NID_pkcs7_enveloped)
		{
		CMSerr(CMS_F_CMS_DECRYPT, CMS_R_TYPE_NOT_ENVELOPED_DATA);
		return 0;
		}
	if (!dcont && !check_content(cms))
		return 0;
	if (pk)
int CMS_decrypt_set1_pkey(CMS_ContentInfo *cms, EVP_PKEY *pk, X509 *cert)
	{
	STACK_OF(CMS_RecipientInfo) *ris;
	CMS_RecipientInfo *ri;
	int i, r;
	ris = CMS_get0_RecipientInfos(cms);
	for (i = 0; i < sk_CMS_RecipientInfo_num(ris); i++)
		{
@@ -520,26 +508,83 @@ int CMS_decrypt(CMS_ContentInfo *cms, EVP_PKEY *pk, X509 *cert,
		/* If we have a cert try matching RecipientInfo
		 * otherwise try them all.
		 */
			if (!cert ||
			(CMS_RecipientInfo_ktri_cert_cmp(ri, cert) == 0))
		if (!cert || (CMS_RecipientInfo_ktri_cert_cmp(ri, cert) == 0))
			{
			CMS_RecipientInfo_set0_pkey(ri, pk);
			r = CMS_RecipientInfo_decrypt(cms, ri);
			CMS_RecipientInfo_set0_pkey(ri, NULL);
			if (r > 0)
					break;
				return 1;
			if (cert)
				{
				CMSerr(CMS_F_CMS_DECRYPT_SET1_PKEY,
						CMS_R_DECRYPT_ERROR);
				return 0;
				}
			ERR_clear_error();
			}
		}

		if (i == sk_CMS_RecipientInfo_num(ris))
	CMSerr(CMS_F_CMS_DECRYPT_SET1_PKEY, CMS_R_NO_MATCHING_RECIPIENT);
	return 0;

	}

int CMS_decrypt_set1_key(CMS_ContentInfo *cms, 
				unsigned char *key, size_t keylen,
				unsigned char *id, size_t idlen)
	{
	STACK_OF(CMS_RecipientInfo) *ris;
	CMS_RecipientInfo *ri;
	int i, r;
	ris = CMS_get0_RecipientInfos(cms);
	for (i = 0; i < sk_CMS_RecipientInfo_num(ris); i++)
		{
		ri = sk_CMS_RecipientInfo_value(ris, i);
		if (CMS_RecipientInfo_type(ri) != CMS_RECIPINFO_KEK)
				continue;

		/* If we have an id try matching RecipientInfo
		 * otherwise try them all.
		 */
		if (!id || (CMS_RecipientInfo_kekri_id_cmp(ri, id, idlen) == 0))
			{
			CMS_RecipientInfo_set0_key(ri, key, keylen);
			r = CMS_RecipientInfo_decrypt(cms, ri);
			CMS_RecipientInfo_set0_key(ri, NULL, 0);
			if (r > 0)
				return 1;
			if (id)
				{
			CMSerr(CMS_F_CMS_DECRYPT, CMS_R_NO_MATCHING_RECIPIENT);
				CMSerr(CMS_F_CMS_DECRYPT_SET1_KEY,
						CMS_R_DECRYPT_ERROR);
				return 0;
				}
			ERR_clear_error();
			}
		}

	CMSerr(CMS_F_CMS_DECRYPT_SET1_KEY, CMS_R_NO_MATCHING_RECIPIENT);
	return 0;

	}
	
int CMS_decrypt(CMS_ContentInfo *cms, EVP_PKEY *pk, X509 *cert,
				BIO *dcont, BIO *out,
				unsigned int flags)
	{
	int r;
	BIO *cont;
	if (OBJ_obj2nid(CMS_get0_type(cms)) != NID_pkcs7_enveloped)
		{
		CMSerr(CMS_F_CMS_DECRYPT, CMS_R_TYPE_NOT_ENVELOPED_DATA);
		return 0;
		}
	if (!dcont && !check_content(cms))
		return 0;
	if (pk && !CMS_decrypt_set1_pkey(cms, pk, cert))
		return 0;

	cont = CMS_dataInit(cms, dcont);
	if (!cont)
		return 0;
Loading