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

Preliminary support for enveloped data content type creation.

Fix signed data creation so versions are only corrected if structure is
being created.
parent 1e26a8ba
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -169,6 +169,9 @@ int CMS_decrypt(CMS_ContentInfo *cms, EVP_PKEY *pkey, X509 *cert,

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);
CMS_RecipientInfo *CMS_add1_recipient_cert(CMS_ContentInfo *cms,
					X509 *recip, unsigned int flags);
int CMS_RecipientInfo_ktri_cert_cmp(CMS_RecipientInfo *ri, X509 *cert);
int CMS_RecipientInfo_ktri_get0_algs(CMS_RecipientInfo *ri,
					EVP_PKEY **pk, X509 **recip,
@@ -290,6 +293,7 @@ void ERR_load_CMS_strings(void);
#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_ENCRYPT				 154
#define CMS_F_CMS_ENCRYPTEDCONTENT_DECRYPT_BIO		 146
#define CMS_F_CMS_ENCRYPTEDCONTENT_ENCRYPT_BIO		 144
#define CMS_F_CMS_ENCRYPTEDCONTENT_INIT_BIO		 148
@@ -299,6 +303,8 @@ void ERR_load_CMS_strings(void);
#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_ENVELOPEDDATA_CREATE			 153
#define CMS_F_CMS_ENVELOPEDDATA_INIT_BIO		 156
#define CMS_F_CMS_ENVELOPED_DATA_INIT			 114
#define CMS_F_CMS_FINAL					 115
#define CMS_F_CMS_GET0_CERTIFICATE_CHOICES		 116
@@ -309,6 +315,7 @@ void ERR_load_CMS_strings(void);
#define CMS_F_CMS_GET0_SIGNED				 121
#define CMS_F_CMS_RECIPIENTINFO_DECRYPT			 150
#define CMS_F_CMS_RECIPIENTINFO_KTRI_CERT_CMP		 122
#define CMS_F_CMS_RECIPIENTINFO_KTRI_ENCRYPT		 155
#define CMS_F_CMS_RECIPIENTINFO_KTRI_GET0_ALGS		 123
#define CMS_F_CMS_RECIPIENTINFO_KTRI_GET0_SIGNER_ID	 124
#define CMS_F_CMS_SET1_SIGNERIDENTIFIER			 125
@@ -340,6 +347,7 @@ void ERR_load_CMS_strings(void);
#define CMS_R_CTRL_FAILURE				 108
#define CMS_R_ERROR_GETTING_PUBLIC_KEY			 109
#define CMS_R_ERROR_READING_MESSAGEDIGEST_ATTRIBUTE	 110
#define CMS_R_ERROR_SETTING_RECIPIENTINFO		 150
#define CMS_R_INVALID_KEY_LENGTH			 140
#define CMS_R_MD_BIO_INIT_ERROR				 111
#define CMS_R_MESSAGEDIGEST_ATTRIBUTE_WRONG_LENGTH	 112
@@ -358,6 +366,7 @@ void ERR_load_CMS_strings(void);
#define CMS_R_NO_PUBLIC_KEY				 121
#define CMS_R_NO_SIGNERS				 122
#define CMS_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE	 123
#define CMS_R_RECIPIENT_ERROR				 149
#define CMS_R_SIGNER_CERTIFICATE_NOT_FOUND		 124
#define CMS_R_SIGNFINAL_ERROR				 125
#define CMS_R_SMIME_TEXT_ERROR				 126
@@ -373,6 +382,7 @@ void ERR_load_CMS_strings(void);
#define CMS_R_UNKNOWN_ID				 133
#define CMS_R_UNSUPPORTED_COMPRESSION_ALGORITHM		 134
#define CMS_R_UNSUPPORTED_CONTENT_TYPE			 135
#define CMS_R_UNSUPPORTED_RECIPIENT_TYPE		 151
#define CMS_R_UNSUPPORTED_TYPE				 136
#define CMS_R_VERIFICATION_FAILURE			 137

+14 −9
Original line number Diff line number Diff line
@@ -92,7 +92,14 @@ BIO *cms_EncryptedContent_init_bio(CMS_EncryptedContentInfo *ec)
	BIO_get_cipher_ctx(b, &ctx);

	if (enc)
		{
		ciph = ec->cipher;
		/* If not keeping key set cipher to NULL so subsequent calls
		 * decrypt.
		 */
		if (ec->key)
			ec->cipher = NULL;
		}
	else
		{
		ciph = EVP_get_cipherbyobj(calg->algorithm);
@@ -112,12 +119,10 @@ BIO *cms_EncryptedContent_init_bio(CMS_EncryptedContentInfo *ec)
		goto err;
		}

	if (enc)
		calg->algorithm = OBJ_nid2obj(EVP_CIPHER_CTX_type(ctx));

	if (enc)
		{
		int ivlen;
		calg->algorithm = OBJ_nid2obj(EVP_CIPHER_CTX_type(ctx));
		/* Generate a random IV if we need one */
		ivlen = EVP_CIPHER_CTX_iv_length(ctx);
		if (ivlen > 0)
@@ -200,7 +205,7 @@ BIO *cms_EncryptedContent_init_bio(CMS_EncryptedContentInfo *ec)
	return NULL;
	}

static int cms_EncryptedContent_init(CMS_EncryptedContentInfo *ec, 
int cms_EncryptedContent_init(CMS_EncryptedContentInfo *ec, 
				const EVP_CIPHER *cipher,
				const unsigned char *key, size_t keylen)
	{
@@ -252,7 +257,7 @@ int CMS_EncryptedData_set1_key(CMS_ContentInfo *cms, const EVP_CIPHER *ciph,
BIO *cms_EncryptedData_init_bio(CMS_ContentInfo *cms)
	{
	CMS_EncryptedData *enc = cms->d.encryptedData;
	if (enc->unprotectedAttrs)
	if (enc->encryptedContentInfo->cipher && enc->unprotectedAttrs)
		enc->version = 2;
	return cms_EncryptedContent_init_bio(enc->encryptedContentInfo);
	}
+142 −9
Original line number Diff line number Diff line
@@ -104,7 +104,7 @@ static CMS_EnvelopedData *cms_enveloped_data_init(CMS_ContentInfo *cms)
STACK_OF(CMS_RecipientInfo) *CMS_get0_RecipientInfos(CMS_ContentInfo *cms)
	{
	CMS_EnvelopedData *env;
	env = cms_enveloped_data_init(cms);
	env = cms_get0_enveloped(cms);
	if (!env)
		return NULL;
	return env->recipientInfos;
@@ -115,10 +115,30 @@ 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;
	}

/* Add a recipient certificate. For now only handle key transport.
 * If we ever handle key agreement will need updating.
 */
#if 0 /* currently unused/undeclared */
CMS_RecipientInfo *CMS_add1_recipient_cert(CMS_ContentInfo *cms,
					X509 *recip, unsigned int flags)
	{
@@ -127,17 +147,16 @@ CMS_RecipientInfo *CMS_add1_recipient_cert(CMS_ContentInfo *cms,
	CMS_EnvelopedData *env;
	EVP_PKEY *pk = NULL;
	int i, type;
	/* Init enveloped data */
	env = cms_enveloped_data_init(cms);
	env = cms_get0_enveloped(cms);
	if (!env)
		goto err;

	/* Initialized recipient info */
	/* Initialize recipient info */
	ri = M_ASN1_new_of(CMS_RecipientInfo);
	if (!ri)
		goto merr;

	/* Initialize and add key transrport recipient info */
	/* Initialize and add key transport recipient info */

	ri->d.ktri = M_ASN1_new_of(CMS_KeyTransRecipientInfo);
	if (!ri->d.ktri)
@@ -155,7 +174,6 @@ CMS_RecipientInfo *CMS_add1_recipient_cert(CMS_ContentInfo *cms,
		goto err;
		}
	CRYPTO_add(&recip->references, 1, CRYPTO_LOCK_X509);
	CRYPTO_add(&pk->references, 1, CRYPTO_LOCK_EVP_PKEY);
	ktri->pkey = pk;
	ktri->recip = recip;

@@ -208,7 +226,6 @@ CMS_RecipientInfo *CMS_add1_recipient_cert(CMS_ContentInfo *cms,
	return NULL;

	}
#endif

int CMS_RecipientInfo_ktri_get0_algs(CMS_RecipientInfo *ri,
					EVP_PKEY **pk, X509 **recip,
@@ -262,6 +279,71 @@ int CMS_RecipientInfo_ktri_cert_cmp(CMS_RecipientInfo *ri, X509 *cert)
	return cms_SignerIdentifier_cert_cmp(ri->d.ktri->rid, cert);
	}

/* 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;
	EVP_PKEY_CTX *pctx = NULL;
	unsigned char *ek = NULL;
	size_t 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;

	pctx = EVP_PKEY_CTX_new(ktri->pkey, NULL);
	if (!pctx)
		return 0;

	if (EVP_PKEY_encrypt_init(pctx) <= 0)
		goto err;

	if (EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_ENCRYPT,
				EVP_PKEY_CTRL_CMS_ENCRYPT, 0, ri) <= 0)
		{
		CMSerr(CMS_F_CMS_RECIPIENTINFO_KTRI_ENCRYPT, CMS_R_CTRL_ERROR);
		goto err;
		}

	if (EVP_PKEY_encrypt(pctx, NULL, &eklen, ec->key, ec->keylen) <= 0)
		goto err;

	ek = OPENSSL_malloc(eklen);

	if (ek == NULL)
		{
		CMSerr(CMS_F_CMS_RECIPIENTINFO_KTRI_ENCRYPT,
							ERR_R_MALLOC_FAILURE);
		goto err;
		}

	if (EVP_PKEY_encrypt(pctx, ek, &eklen, ec->key, ec->keylen) <= 0)
		goto err;

	ASN1_STRING_set0(ktri->encryptedKey, ek, eklen);
	ek = NULL;

	ret = 1;

	err:
	if (pctx)
		EVP_PKEY_CTX_free(pctx);
	if (ek)
		OPENSSL_free(ek);
	return ret;

	}

int CMS_RecipientInfo_decrypt(CMS_ContentInfo *cms, CMS_RecipientInfo *ri,
			       EVP_PKEY *pkey)
	{
@@ -332,6 +414,57 @@ int CMS_RecipientInfo_decrypt(CMS_ContentInfo *cms, CMS_RecipientInfo *ri,
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;
	return cms_EncryptedContent_init_bio(ec);
	ret = cms_EncryptedContent_init_bio(ec);

	/* If error or no cipher end of processing */

	if (!ret || !ec->cipher)
		return ret;


	rinfos = cms->d.envelopedData->recipientInfos;

	for (i = 0; i < sk_CMS_RecipientInfo_num(rinfos); i++)
		{
		ri = sk_CMS_RecipientInfo_value(rinfos, i);
		if (ri->type == CMS_RECIPINFO_TRANS)
			r = cms_RecipientInfo_ktri_encrypt(cms, ri);
		else
			{
			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;

	}
+8 −1
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_ADD1_RECIPIENT_CERT),	"CMS_ADD1_RECIPIENT_CERT"},
{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"},
{ERR_FUNC(CMS_F_CMS_BIO_TO_ENCRYPTEDCONTENT),	"CMS_BIO_TO_ENCRYPTEDCONTENT"},
@@ -91,6 +91,7 @@ static ERR_STRING_DATA CMS_str_functs[]=
{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_ENCRYPT),	"CMS_encrypt"},
{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"},
@@ -100,6 +101,8 @@ static ERR_STRING_DATA CMS_str_functs[]=
{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_ENVELOPEDDATA_CREATE),	"CMS_EnvelopedData_create"},
{ERR_FUNC(CMS_F_CMS_ENVELOPEDDATA_INIT_BIO),	"CMS_ENVELOPEDDATA_INIT_BIO"},
{ERR_FUNC(CMS_F_CMS_ENVELOPED_DATA_INIT),	"CMS_ENVELOPED_DATA_INIT"},
{ERR_FUNC(CMS_F_CMS_FINAL),	"CMS_final"},
{ERR_FUNC(CMS_F_CMS_GET0_CERTIFICATE_CHOICES),	"CMS_GET0_CERTIFICATE_CHOICES"},
@@ -110,6 +113,7 @@ static ERR_STRING_DATA CMS_str_functs[]=
{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_KTRI_CERT_CMP),	"CMS_RecipientInfo_ktri_cert_cmp"},
{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_SET1_SIGNERIDENTIFIER),	"CMS_SET1_SIGNERIDENTIFIER"},
@@ -144,6 +148,7 @@ static ERR_STRING_DATA CMS_str_reasons[]=
{ERR_REASON(CMS_R_CTRL_FAILURE)          ,"ctrl failure"},
{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_RECIPIENTINFO),"error setting recipientinfo"},
{ERR_REASON(CMS_R_INVALID_KEY_LENGTH)    ,"invalid key length"},
{ERR_REASON(CMS_R_MD_BIO_INIT_ERROR)     ,"md bio init error"},
{ERR_REASON(CMS_R_MESSAGEDIGEST_ATTRIBUTE_WRONG_LENGTH),"messagedigest attribute wrong length"},
@@ -162,6 +167,7 @@ static ERR_STRING_DATA CMS_str_reasons[]=
{ERR_REASON(CMS_R_NO_PUBLIC_KEY)         ,"no public key"},
{ERR_REASON(CMS_R_NO_SIGNERS)            ,"no signers"},
{ERR_REASON(CMS_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE),"private key does not match certificate"},
{ERR_REASON(CMS_R_RECIPIENT_ERROR)       ,"recipient error"},
{ERR_REASON(CMS_R_SIGNER_CERTIFICATE_NOT_FOUND),"signer certificate not found"},
{ERR_REASON(CMS_R_SIGNFINAL_ERROR)       ,"signfinal error"},
{ERR_REASON(CMS_R_SMIME_TEXT_ERROR)      ,"smime text error"},
@@ -177,6 +183,7 @@ static ERR_STRING_DATA CMS_str_reasons[]=
{ERR_REASON(CMS_R_UNKNOWN_ID)            ,"unknown id"},
{ERR_REASON(CMS_R_UNSUPPORTED_COMPRESSION_ALGORITHM),"unsupported compression algorithm"},
{ERR_REASON(CMS_R_UNSUPPORTED_CONTENT_TYPE),"unsupported content type"},
{ERR_REASON(CMS_R_UNSUPPORTED_RECIPIENT_TYPE),"unsupported recipient type"},
{ERR_REASON(CMS_R_UNSUPPORTED_TYPE)      ,"unsupported type"},
{ERR_REASON(CMS_R_VERIFICATION_FAILURE)  ,"verification failure"},
{0,NULL}
+5 −0
Original line number Diff line number Diff line
@@ -123,6 +123,8 @@ struct CMS_EncapsulatedContentInfo_st
	{
	ASN1_OBJECT *eContentType;
	ASN1_OCTET_STRING *eContent;
	/* Set to 1 if incomplete structure only part set up */
	int partial;
	};

struct CMS_SignerInfo_st
@@ -411,6 +413,9 @@ int cms_DigestAlgorithm_find_ctx(EVP_MD_CTX *mctx, BIO *chain,

BIO *cms_EncryptedContent_init_bio(CMS_EncryptedContentInfo *ec);
BIO *cms_EncryptedData_init_bio(CMS_ContentInfo *cms);
int cms_EncryptedContent_init(CMS_EncryptedContentInfo *ec, 
				const EVP_CIPHER *cipher,
				const unsigned char *key, size_t keylen);

BIO *cms_EnvelopedData_init_bio(CMS_ContentInfo *cms);
	
Loading