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

Reorganise encrypted content info code to avoid duplication and be more

consistent with other content types.
parent b820455c
Loading
Loading
Loading
Loading
+10 −1
Original line number Diff line number Diff line
@@ -142,7 +142,7 @@ int CMS_EncryptedData_decrypt(CMS_ContentInfo *cms,
				const unsigned char *key, size_t keylen,
				BIO *dcont, BIO *out, unsigned int flags);

int CMS_EncryptedData_set1_key(BIO *b, CMS_ContentInfo *cms,
int CMS_EncryptedData_set1_key(CMS_ContentInfo *cms, const EVP_CIPHER *ciph,
				const unsigned char *key, size_t keylen);

int CMS_verify(CMS_ContentInfo *cms, STACK_OF(X509) *certs,
@@ -249,6 +249,7 @@ void ERR_load_CMS_strings(void);
#define CMS_F_CMS_ADD1_SIGNER				 100
#define CMS_F_CMS_ADD1_SIGNINGTIME			 101
#define CMS_F_CMS_BIO_TO_ENCRYPTEDCONTENT		 137
#define CMS_F_CMS_BIO_TO_ENCRYPTEDCONTENT_BIO		 142
#define CMS_F_CMS_COMPRESS				 102
#define CMS_F_CMS_COMPRESSEDDATA_CREATE			 103
#define CMS_F_CMS_COMPRESSEDDATA_INIT_BIO		 104
@@ -257,12 +258,19 @@ void ERR_load_CMS_strings(void);
#define CMS_F_CMS_DATA					 107
#define CMS_F_CMS_DATAFINAL				 108
#define CMS_F_CMS_DATAINIT				 109
#define CMS_F_CMS_DECRYPTEDCONTENT_DECRYPT_BIO		 145
#define CMS_F_CMS_DECRYPTEDCONTENT_ENCRYPT_BIO		 143
#define CMS_F_CMS_DIGESTALGORITHM_FIND_CTX		 110
#define CMS_F_CMS_DIGESTALGORITHM_INIT_BIO		 111
#define CMS_F_CMS_DIGESTEDDATA_DO_FINAL			 112
#define CMS_F_CMS_DIGEST_VERIFY				 113
#define CMS_F_CMS_ENCRYPTEDCONTENT_DECRYPT_BIO		 146
#define CMS_F_CMS_ENCRYPTEDCONTENT_ENCRYPT_BIO		 144
#define CMS_F_CMS_ENCRYPTEDCONTENT_INIT_BIO		 148
#define CMS_F_CMS_ENCRYPTEDCONTENT_TO_BIO		 138
#define CMS_F_CMS_ENCRYPTEDDATA_DECRYPT			 140
#define CMS_F_CMS_ENCRYPTEDDATA_INIT_BIO		 147
#define CMS_F_CMS_ENCRYPTEDDATA_SET1_KEY		 141
#define CMS_F_CMS_ENCRYPTED_DATA_DECRYPT		 139
#define CMS_F_CMS_ENVELOPED_DATA_INIT			 114
#define CMS_F_CMS_FINAL					 115
@@ -307,6 +315,7 @@ void ERR_load_CMS_strings(void);
#define CMS_R_MD_BIO_INIT_ERROR				 111
#define CMS_R_MESSAGEDIGEST_ATTRIBUTE_WRONG_LENGTH	 112
#define CMS_R_MESSAGEDIGEST_WRONG_LENGTH		 113
#define CMS_R_NOT_ENCRYPTED_DATA			 143
#define CMS_R_NOT_KEY_TRANSPORT				 114
#define CMS_R_NOT_SUPPORTED_FOR_THIS_KEY_TYPE		 115
#define CMS_R_NO_CONTENT				 116
+112 −83
Original line number Diff line number Diff line
@@ -63,135 +63,164 @@

/* CMS EncryptedData Utilities */

/* Set up EncryptedContentInfo based on supplied cipher bio */
DECLARE_ASN1_ITEM(CMS_EncryptedData)

int cms_bio_to_EncryptedContent(CMS_EncryptedContentInfo *ec,
					const unsigned char *key, int keylen,
					BIO *b)
/* Return BIO based on EncryptedContentInfo and key */

BIO *cms_EncryptedContent_init_bio(CMS_EncryptedContentInfo *ec)
	{
	EVP_CIPHER_CTX *ctx = NULL;
	unsigned char iv[EVP_MAX_IV_LENGTH], *piv;
	int ivlen;
	BIO *b;
	EVP_CIPHER_CTX *ctx;
	const EVP_CIPHER *ciph;
	X509_ALGOR *calg = ec->contentEncryptionAlgorithm;
	unsigned char iv[EVP_MAX_IV_LENGTH], *piv = NULL;

	int enc;

	enc = ec->cipher ? 1 : 0;

	b = BIO_new(BIO_f_cipher());
	if (!b)
		{
		CMSerr(CMS_F_CMS_ENCRYPTEDCONTENT_INIT_BIO,
							ERR_R_MALLOC_FAILURE);
		return NULL;
		}

	BIO_get_cipher_ctx(b, &ctx);

	if (enc)
		calg->algorithm = OBJ_nid2obj(EVP_CIPHER_CTX_type(ctx));
	else
		{
		ciph = EVP_get_cipherbyobj(calg->algorithm);

		if (!ciph)
			{
			CMSerr(CMS_F_CMS_ENCRYPTEDCONTENT_INIT_BIO,
							CMS_R_UNKNOWN_CIPHER);
			goto err;
			}
		}

	if (EVP_CipherInit_ex(ctx, ciph, NULL, NULL, NULL, enc) <= 0)
		{
		CMSerr(CMS_F_CMS_ENCRYPTEDCONTENT_INIT_BIO,
				CMS_R_CIPHER_INITIALISATION_ERROR);
		goto err;
		}

	/* If necessary set key length */

	if (keylen != EVP_CIPHER_CTX_key_length(ctx))
	if (ec->keylen != EVP_CIPHER_CTX_key_length(ctx))
		{
		if (EVP_CIPHER_CTX_set_key_length(ctx, keylen) <= 0)
		if (EVP_CIPHER_CTX_set_key_length(ctx, ec->keylen) <= 0)
			{
			CMSerr(CMS_F_CMS_BIO_TO_ENCRYPTEDCONTENT,
			CMSerr(CMS_F_CMS_ENCRYPTEDCONTENT_INIT_BIO,
				CMS_R_INVALID_KEY_LENGTH);
			return 0;
			goto err;
			}
		}

	if (enc)
		{
		int ivlen;
		/* Generate a random IV if we need one */

		ivlen = EVP_CIPHER_CTX_iv_length(ctx);
		if (ivlen > 0)
			{
			if (RAND_pseudo_bytes(iv, ivlen) <= 0)
			return 0;
				goto err;
			piv = iv;
			}
	else
		piv = NULL;
		}
	else if (EVP_CIPHER_asn1_to_param(ctx, calg->parameter) <= 0)
			{
			CMSerr(CMS_F_CMS_ENCRYPTEDCONTENT_INIT_BIO,
				CMS_R_CIPHER_PARAMETER_INITIALISATION_ERROR);
			goto err;
			}

	if (EVP_CipherInit_ex(ctx, NULL, NULL, key, piv, 1) <= 0)
	if (EVP_CipherInit_ex(ctx, NULL, NULL, ec->key, piv, enc) <= 0)
		{
		CMSerr(CMS_F_CMS_BIO_TO_ENCRYPTEDCONTENT,
		CMSerr(CMS_F_CMS_ENCRYPTEDCONTENT_INIT_BIO,
				CMS_R_CIPHER_INITIALISATION_ERROR);
		return 0;
		goto err;
		}

	ec->contentEncryptionAlgorithm->algorithm =
			OBJ_nid2obj(EVP_CIPHER_CTX_type(ctx));

	if (piv)
		{
		ec->contentEncryptionAlgorithm->parameter = ASN1_TYPE_new();
		if (!ec->contentEncryptionAlgorithm->parameter)
		calg->parameter = ASN1_TYPE_new();
		if (!calg->parameter)
			{
			CMSerr(CMS_F_CMS_BIO_TO_ENCRYPTEDCONTENT,
			CMSerr(CMS_F_CMS_ENCRYPTEDCONTENT_INIT_BIO,
							ERR_R_MALLOC_FAILURE);
			return 0;
			goto err;
			}
		if (EVP_CIPHER_param_to_asn1(ctx, 
			ec->contentEncryptionAlgorithm->parameter) <= 0)
		if (EVP_CIPHER_param_to_asn1(ctx, calg->parameter) <= 0)
			{
			CMSerr(CMS_F_CMS_BIO_TO_ENCRYPTEDCONTENT,
			CMSerr(CMS_F_CMS_ENCRYPTEDCONTENT_INIT_BIO,
				CMS_R_CIPHER_PARAMETER_INITIALISATION_ERROR);
			return 0;
			goto err;
			}
		}
	return b;

	return 1;
	err:
	BIO_free(b);
	return NULL;
	}

/* Return BIO based on EncryptedContentInfo and key */

int cms_EncryptedContent_to_bio(BIO *b, CMS_EncryptedContentInfo *ec,
					const unsigned char *key, int keylen)
	{
	EVP_CIPHER_CTX *ctx;
	const EVP_CIPHER *ciph;
	BIO_get_cipher_ctx(b, &ctx);

	ciph = EVP_get_cipherbyobj(ec->contentEncryptionAlgorithm->algorithm);

	if (!ciph)
int cms_EncryptedContent_init(CMS_EncryptedContentInfo *ec, 
				const EVP_CIPHER *cipher,
				const unsigned char *key, size_t keylen)
	{
		CMSerr(CMS_F_CMS_ENCRYPTEDCONTENT_TO_BIO, CMS_R_UNKNOWN_CIPHER);
		goto err;
	ec->cipher = cipher;
	ec->key = OPENSSL_malloc(keylen);
	if (!ec->key)
		return 0;
	if (cipher)
		ec->contentType = OBJ_nid2obj(NID_pkcs7_data);
	memcpy(ec->key, key, keylen);
	ec->keylen = keylen;
	return 1;
	}

	if (EVP_CipherInit_ex(ctx, ciph, NULL, NULL, NULL, 0) <= 0)
int CMS_EncryptedData_set1_key(CMS_ContentInfo *cms, const EVP_CIPHER *ciph,
				const unsigned char *key, size_t keylen)
	{
		CMSerr(CMS_F_CMS_ENCRYPTEDCONTENT_TO_BIO,
				CMS_R_CIPHER_INITIALISATION_ERROR);
		goto err;
		}

	/* If necessary set key length */

	if (keylen != EVP_CIPHER_CTX_key_length(ctx))
	CMS_EncryptedContentInfo *ec;
	if (ciph)
		{
		if (EVP_CIPHER_CTX_set_key_length(ctx, keylen) <= 0)
		cms->d.encryptedData = M_ASN1_new_of(CMS_EncryptedData);
		if (!cms->d.encryptedData)
			{
			CMSerr(CMS_F_CMS_ENCRYPTEDCONTENT_TO_BIO,
				CMS_R_INVALID_KEY_LENGTH);
			goto err;
			CMSerr(CMS_F_CMS_ENCRYPTEDDATA_SET1_KEY,
				ERR_R_MALLOC_FAILURE);
			return 0;
			}
		cms->contentType = OBJ_nid2obj(NID_pkcs7_encrypted);
		cms->d.encryptedData->version = 0;
		}

	if (EVP_CipherInit_ex(ctx, NULL, NULL, key, NULL, 0) <= 0)
	else if (OBJ_obj2nid(cms->contentType) != NID_pkcs7_encrypted)
		{
		CMSerr(CMS_F_CMS_ENCRYPTEDCONTENT_TO_BIO,
				CMS_R_CIPHER_INITIALISATION_ERROR);
		goto err;
		}

	if (EVP_CIPHER_asn1_to_param(ctx, 
			ec->contentEncryptionAlgorithm->parameter) <= 0)
			{
			CMSerr(CMS_F_CMS_ENCRYPTEDCONTENT_TO_BIO,
				CMS_R_CIPHER_PARAMETER_INITIALISATION_ERROR);
			goto err;
			}
	return 1;

	err:
		CMSerr(CMS_F_CMS_ENCRYPTEDDATA_SET1_KEY,
						CMS_R_NOT_ENCRYPTED_DATA);
		return 0;
		}
	ec = cms->d.encryptedData->encryptedContentInfo;
	return cms_EncryptedContent_init(ec, ciph, key, keylen);
	}

int CMS_EncryptedData_set1_key(BIO *b, CMS_ContentInfo *cms,
				const unsigned char *key, size_t keylen)
BIO *cms_EncryptedData_init_bio(CMS_ContentInfo *cms)
	{
	CMS_EncryptedContentInfo *ec;
	if (OBJ_obj2nid(cms->contentType) != NID_pkcs7_encrypted)
		return 0;
		{
		CMSerr(CMS_F_CMS_ENCRYPTEDDATA_INIT_BIO,
						CMS_R_NOT_ENCRYPTED_DATA);
		return NULL;
		}
	ec = cms->d.encryptedData->encryptedContentInfo;
	return cms_EncryptedContent_to_bio(b, ec, key, keylen);
	return cms_EncryptedContent_init_bio(ec);
	}
+9 −0
Original line number Diff line number Diff line
@@ -74,6 +74,7 @@ static ERR_STRING_DATA CMS_str_functs[]=
{ERR_FUNC(CMS_F_CMS_ADD1_SIGNER),	"CMS_add1_signer"},
{ERR_FUNC(CMS_F_CMS_ADD1_SIGNINGTIME),	"CMS_ADD1_SIGNINGTIME"},
{ERR_FUNC(CMS_F_CMS_BIO_TO_ENCRYPTEDCONTENT),	"CMS_BIO_TO_ENCRYPTEDCONTENT"},
{ERR_FUNC(CMS_F_CMS_BIO_TO_ENCRYPTEDCONTENT_BIO),	"CMS_BIO_TO_ENCRYPTEDCONTENT_BIO"},
{ERR_FUNC(CMS_F_CMS_COMPRESS),	"CMS_compress"},
{ERR_FUNC(CMS_F_CMS_COMPRESSEDDATA_CREATE),	"CMS_COMPRESSEDDATA_CREATE"},
{ERR_FUNC(CMS_F_CMS_COMPRESSEDDATA_INIT_BIO),	"CMS_COMPRESSEDDATA_INIT_BIO"},
@@ -82,12 +83,19 @@ static ERR_STRING_DATA CMS_str_functs[]=
{ERR_FUNC(CMS_F_CMS_DATA),	"CMS_data"},
{ERR_FUNC(CMS_F_CMS_DATAFINAL),	"CMS_dataFinal"},
{ERR_FUNC(CMS_F_CMS_DATAINIT),	"CMS_dataInit"},
{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_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"},
{ERR_FUNC(CMS_F_CMS_DIGEST_VERIFY),	"CMS_digest_verify"},
{ERR_FUNC(CMS_F_CMS_ENCRYPTEDCONTENT_DECRYPT_BIO),	"CMS_ENCRYPTEDCONTENT_DECRYPT_BIO"},
{ERR_FUNC(CMS_F_CMS_ENCRYPTEDCONTENT_ENCRYPT_BIO),	"CMS_ENCRYPTEDCONTENT_ENCRYPT_BIO"},
{ERR_FUNC(CMS_F_CMS_ENCRYPTEDCONTENT_INIT_BIO),	"CMS_ENCRYPTEDCONTENT_INIT_BIO"},
{ERR_FUNC(CMS_F_CMS_ENCRYPTEDCONTENT_TO_BIO),	"CMS_ENCRYPTEDCONTENT_TO_BIO"},
{ERR_FUNC(CMS_F_CMS_ENCRYPTEDDATA_DECRYPT),	"CMS_EncryptedData_decrypt"},
{ERR_FUNC(CMS_F_CMS_ENCRYPTEDDATA_INIT_BIO),	"CMS_ENCRYPTEDDATA_INIT_BIO"},
{ERR_FUNC(CMS_F_CMS_ENCRYPTEDDATA_SET1_KEY),	"CMS_EncryptedData_set1_key"},
{ERR_FUNC(CMS_F_CMS_ENCRYPTED_DATA_DECRYPT),	"CMS_ENCRYPTED_DATA_DECRYPT"},
{ERR_FUNC(CMS_F_CMS_ENVELOPED_DATA_INIT),	"CMS_ENVELOPED_DATA_INIT"},
{ERR_FUNC(CMS_F_CMS_FINAL),	"CMS_final"},
@@ -135,6 +143,7 @@ static ERR_STRING_DATA CMS_str_reasons[]=
{ERR_REASON(CMS_R_MD_BIO_INIT_ERROR)     ,"md bio init error"},
{ERR_REASON(CMS_R_MESSAGEDIGEST_ATTRIBUTE_WRONG_LENGTH),"messagedigest attribute wrong length"},
{ERR_REASON(CMS_R_MESSAGEDIGEST_WRONG_LENGTH),"messagedigest wrong length"},
{ERR_REASON(CMS_R_NOT_ENCRYPTED_DATA)    ,"not encrypted data"},
{ERR_REASON(CMS_R_NOT_KEY_TRANSPORT)     ,"not key transport"},
{ERR_REASON(CMS_R_NOT_SUPPORTED_FOR_THIS_KEY_TYPE),"not supported for this key type"},
{ERR_REASON(CMS_R_NO_CONTENT)            ,"no content"},
+8 −6
Original line number Diff line number Diff line
@@ -169,6 +169,10 @@ struct CMS_EncryptedContentInfo_st
	ASN1_OBJECT *contentType;
	X509_ALGOR *contentEncryptionAlgorithm;
	ASN1_OCTET_STRING *encryptedContent;
	/* Content encryption algorithm and key */
	const EVP_CIPHER *cipher;
	unsigned char *key;
	size_t keylen;
	};

struct CMS_RecipientInfo_st
@@ -255,7 +259,7 @@ struct CMS_KEKRecipientInfo_st
 	CMS_KEKIdentifier *kekid;
 	X509_ALGOR *keyEncryptionAlgorithm;
 	ASN1_OCTET_STRING *encryptedKey;
	/* Extra Info symmetric key to use */
	/* Extra info: symmetric key to use */
	unsigned char *key;
	size_t keylen;
	};
@@ -412,11 +416,9 @@ BIO *cms_DigestAlgorithm_init_bio(X509_ALGOR *digestAlgorithm);
int cms_DigestAlgorithm_find_ctx(EVP_MD_CTX *mctx, BIO *chain,
					X509_ALGOR *mdalg);

int cms_bio_to_EncryptedContent(CMS_EncryptedContentInfo *ec,
					const unsigned char *key, int keylen,
					BIO *b);
int cms_EncryptedContent_to_bio(BIO *b, CMS_EncryptedContentInfo *ec,
					const unsigned char *key, int keylen);
BIO *cms_EncryptedContent_encrypt_bio(CMS_EncryptedContentInfo *ec);
BIO *cms_EncryptedContent_decrypt_bio(CMS_EncryptedContentInfo *ec);
BIO *cms_EncryptedData_init_bio(CMS_ContentInfo *cms);
	
#ifdef  __cplusplus
}
+1 −7
Original line number Diff line number Diff line
@@ -68,12 +68,6 @@ DECLARE_ASN1_ITEM(CMS_RevocationInfoChoice)
DECLARE_STACK_OF(CMS_CertificateChoices)
DECLARE_STACK_OF(CMS_RevocationInfoChoice)

#if 0
IMPLEMENT_ASN1_ALLOC_FUNCTIONS(CMS_CertificateChoices)
IMPLEMENT_ASN1_ALLOC_FUNCTIONS(CMS_RevocationInfoChoice)
#endif


const ASN1_OBJECT *CMS_get0_type(CMS_ContentInfo *cms)
	{
	return cms->contentType;
@@ -140,7 +134,7 @@ BIO *CMS_dataInit(CMS_ContentInfo *cms, BIO *icont)
#endif

		case NID_pkcs7_encrypted:
		cmsbio = BIO_new(BIO_f_cipher());
		cmsbio = cms_EncryptedData_init_bio(cms);
		break;

		default:
Loading