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

CMS public key parameter support.

Add support for customisation of CMS handling of signed and enveloped
data from custom public key parameters.

This will provide support for RSA-PSS and RSA-OAEP but could also be
applied to other algorithms.
parent 211a14f6
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -112,6 +112,7 @@ DECLARE_ASN1_PRINT_FUNCTION(CMS_ContentInfo)
#define CMS_REUSE_DIGEST		0x8000
#define CMS_USE_KEYID			0x10000
#define CMS_DEBUG_DECRYPT		0x20000
#define CMS_KEY_PARAM			0x40000

const ASN1_OBJECT *CMS_get0_type(CMS_ContentInfo *cms);

@@ -190,6 +191,7 @@ int CMS_decrypt_set1_password(CMS_ContentInfo *cms,

STACK_OF(CMS_RecipientInfo) *CMS_get0_RecipientInfos(CMS_ContentInfo *cms);
int CMS_RecipientInfo_type(CMS_RecipientInfo *ri);
EVP_PKEY_CTX *CMS_RecipientInfo_get0_pkey_ctx(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);
@@ -256,6 +258,8 @@ int CMS_SignedData_init(CMS_ContentInfo *cms);
CMS_SignerInfo *CMS_add1_signer(CMS_ContentInfo *cms,
			X509 *signer, EVP_PKEY *pk, const EVP_MD *md,
			unsigned int flags);
EVP_PKEY_CTX *CMS_SignerInfo_get0_pkey_ctx(CMS_SignerInfo *si);
EVP_MD_CTX *CMS_SignerInfo_get0_md_ctx(CMS_SignerInfo *si);
STACK_OF(CMS_SignerInfo) *CMS_get0_SignerInfos(CMS_ContentInfo *cms);

void CMS_SignerInfo_set1_signer_cert(CMS_SignerInfo *si, X509 *signer);
@@ -374,6 +378,7 @@ void ERR_load_CMS_strings(void);
#define CMS_F_CMS_ENVELOPEDDATA_CREATE			 124
#define CMS_F_CMS_ENVELOPEDDATA_INIT_BIO		 125
#define CMS_F_CMS_ENVELOPED_DATA_INIT			 126
#define CMS_F_CMS_ENV_ASN1_CTRL				 171
#define CMS_F_CMS_FINAL					 127
#define CMS_F_CMS_GET0_CERTIFICATE_CHOICES		 128
#define CMS_F_CMS_GET0_CONTENT				 129
@@ -399,6 +404,7 @@ void ERR_load_CMS_strings(void);
#define CMS_F_CMS_RECIPIENTINFO_SET0_KEY		 144
#define CMS_F_CMS_RECIPIENTINFO_SET0_PASSWORD		 168
#define CMS_F_CMS_RECIPIENTINFO_SET0_PKEY		 145
#define CMS_F_CMS_SD_ASN1_CTRL				 170
#define CMS_F_CMS_SET1_SIGNERIDENTIFIER			 146
#define CMS_F_CMS_SET_DETACHED				 147
#define CMS_F_CMS_SIGN					 148
+4 −0
Original line number Diff line number Diff line
@@ -97,6 +97,8 @@ static int cms_si_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
			EVP_PKEY_free(si->pkey);
		if (si->signer)
			X509_free(si->signer);
		if (si->pctx)
			EVP_MD_CTX_cleanup(&si->mctx);
		}
	return 1;
	}
@@ -227,6 +229,8 @@ static int cms_ri_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
				EVP_PKEY_free(ktri->pkey);
			if (ktri->recip)
				X509_free(ktri->recip);
			if (ktri->pctx)
				EVP_PKEY_CTX_free(ktri->pctx);
			}
		else if (ri->type == CMS_RECIPINFO_KEK)
			{
+70 −30
Original line number Diff line number Diff line
@@ -103,6 +103,27 @@ static CMS_EnvelopedData *cms_enveloped_data_init(CMS_ContentInfo *cms)
	return cms_get0_enveloped(cms);
	}

static int cms_env_asn1_ctrl(CMS_RecipientInfo *ri, int cmd)
	{
	EVP_PKEY *pkey = ri->d.ktri->pkey;
	int i;
	if (!pkey->ameth || !pkey->ameth->pkey_ctrl)
		return 1;
	i = pkey->ameth->pkey_ctrl(pkey, ASN1_PKEY_CTRL_CMS_ENVELOPE, cmd, ri);
	if (i == -2)
		{
		CMSerr(CMS_F_CMS_ENV_ASN1_CTRL,
				CMS_R_NOT_SUPPORTED_FOR_THIS_KEY_TYPE);
		return 0;
		}
	if (i <= 0)
		{
		CMSerr(CMS_F_CMS_ENV_ASN1_CTRL, CMS_R_CTRL_FAILURE);
		return 0;
		}
	return 1;
	}

STACK_OF(CMS_RecipientInfo) *CMS_get0_RecipientInfos(CMS_ContentInfo *cms)
	{
	CMS_EnvelopedData *env;
@@ -117,6 +138,13 @@ int CMS_RecipientInfo_type(CMS_RecipientInfo *ri)
	return ri->type;
	}

EVP_PKEY_CTX *CMS_RecipientInfo_get0_pkey_ctx(CMS_RecipientInfo *ri)
	{
	if (ri->type == CMS_RECIPINFO_TRANS)
		return ri->d.ktri->pctx;
	return NULL;
	}

CMS_ContentInfo *CMS_EnvelopedData_create(const EVP_CIPHER *cipher)
	{
	CMS_ContentInfo *cms;
@@ -151,7 +179,7 @@ CMS_RecipientInfo *CMS_add1_recipient_cert(CMS_ContentInfo *cms,
	CMS_KeyTransRecipientInfo *ktri;
	CMS_EnvelopedData *env;
	EVP_PKEY *pk = NULL;
	int i, type;
	int type;
	env = cms_get0_enveloped(cms);
	if (!env)
		goto err;
@@ -200,23 +228,16 @@ CMS_RecipientInfo *CMS_add1_recipient_cert(CMS_ContentInfo *cms,
	if (!cms_set1_SignerIdentifier(ktri->rid, recip, type))
		goto err;

	if (pk->ameth && pk->ameth->pkey_ctrl)
	if (flags & CMS_KEY_PARAM)
		{
		i = pk->ameth->pkey_ctrl(pk, ASN1_PKEY_CTRL_CMS_ENVELOPE,
						0, ri);
		if (i == -2)
			{
			CMSerr(CMS_F_CMS_ADD1_RECIPIENT_CERT,
				CMS_R_NOT_SUPPORTED_FOR_THIS_KEY_TYPE);
		ktri->pctx = EVP_PKEY_CTX_new(ktri->pkey, NULL);
		if (!ktri->pctx)
			return 0;
		if (EVP_PKEY_encrypt_init(ktri->pctx) <= 0)
			goto err;
		}
		if (i <= 0)
			{
			CMSerr(CMS_F_CMS_ADD1_RECIPIENT_CERT,
				CMS_R_CTRL_FAILURE);
	else if (!cms_env_asn1_ctrl(ri, 0))
		goto err;
			}
		}

	if (!sk_CMS_RecipientInfo_push(env->recipientInfos, ri))
		goto merr;
@@ -302,7 +323,7 @@ static int cms_RecipientInfo_ktri_encrypt(CMS_ContentInfo *cms,
	{
	CMS_KeyTransRecipientInfo *ktri;
	CMS_EncryptedContentInfo *ec;
	EVP_PKEY_CTX *pctx = NULL;
	EVP_PKEY_CTX *pctx;
	unsigned char *ek = NULL;
	size_t eklen;

@@ -317,12 +338,22 @@ static int cms_RecipientInfo_ktri_encrypt(CMS_ContentInfo *cms,
	ktri = ri->d.ktri;
	ec = cms->d.envelopedData->encryptedContentInfo;

	pctx = ktri->pctx;

	if (pctx)
		{
		if (!cms_env_asn1_ctrl(ri, 0))
			goto err;
		}
	else
		{
		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)
@@ -353,7 +384,10 @@ static int cms_RecipientInfo_ktri_encrypt(CMS_ContentInfo *cms,

	err:
	if (pctx)
		{
		EVP_PKEY_CTX_free(pctx);
		ktri->pctx = NULL;
		}
	if (ek)
		OPENSSL_free(ek);
	return ret;
@@ -366,7 +400,7 @@ static int cms_RecipientInfo_ktri_decrypt(CMS_ContentInfo *cms,
							CMS_RecipientInfo *ri)
	{
	CMS_KeyTransRecipientInfo *ktri = ri->d.ktri;
	EVP_PKEY_CTX *pctx = NULL;
	EVP_PKEY *pkey = ktri->pkey;
	unsigned char *ek = NULL;
	size_t eklen;
	int ret = 0;
@@ -380,21 +414,24 @@ static int cms_RecipientInfo_ktri_decrypt(CMS_ContentInfo *cms,
		return 0;
		}

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

	if (EVP_PKEY_decrypt_init(pctx) <= 0)
	if (EVP_PKEY_decrypt_init(ktri->pctx) <= 0)
		goto err;

	if (EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_DECRYPT,
	if (!cms_env_asn1_ctrl(ri, 1))
		goto err;

	if (EVP_PKEY_CTX_ctrl(ktri->pctx, -1, EVP_PKEY_OP_DECRYPT,
				EVP_PKEY_CTRL_CMS_DECRYPT, 0, ri) <= 0)
		{
		CMSerr(CMS_F_CMS_RECIPIENTINFO_KTRI_DECRYPT, CMS_R_CTRL_ERROR);
		goto err;
		}

	if (EVP_PKEY_decrypt(pctx, NULL, &eklen,
	if (EVP_PKEY_decrypt(ktri->pctx, NULL, &eklen,
				ktri->encryptedKey->data,
				ktri->encryptedKey->length) <= 0)
		goto err;
@@ -408,7 +445,7 @@ static int cms_RecipientInfo_ktri_decrypt(CMS_ContentInfo *cms,
		goto err;
		}

	if (EVP_PKEY_decrypt(pctx, ek, &eklen,
	if (EVP_PKEY_decrypt(ktri->pctx, ek, &eklen,
				ktri->encryptedKey->data,
				ktri->encryptedKey->length) <= 0)
		{
@@ -428,8 +465,11 @@ static int cms_RecipientInfo_ktri_decrypt(CMS_ContentInfo *cms,
	ec->keylen = eklen;

	err:
	if (pctx)
		EVP_PKEY_CTX_free(pctx);
	if (ktri->pctx)
		{
		EVP_PKEY_CTX_free(ktri->pctx);
		ktri->pctx = NULL;
		}
	if (!ret && ek)
		OPENSSL_free(ek);

+2 −0
Original line number Diff line number Diff line
@@ -103,6 +103,7 @@ static ERR_STRING_DATA CMS_str_functs[]=
{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_ENV_ASN1_CTRL),	"CMS_ENV_ASN1_CTRL"},
{ERR_FUNC(CMS_F_CMS_FINAL),	"CMS_final"},
{ERR_FUNC(CMS_F_CMS_GET0_CERTIFICATE_CHOICES),	"CMS_GET0_CERTIFICATE_CHOICES"},
{ERR_FUNC(CMS_F_CMS_GET0_CONTENT),	"CMS_get0_content"},
@@ -128,6 +129,7 @@ static ERR_STRING_DATA CMS_str_functs[]=
{ERR_FUNC(CMS_F_CMS_RECIPIENTINFO_SET0_KEY),	"CMS_RecipientInfo_set0_key"},
{ERR_FUNC(CMS_F_CMS_RECIPIENTINFO_SET0_PASSWORD),	"CMS_RecipientInfo_set0_password"},
{ERR_FUNC(CMS_F_CMS_RECIPIENTINFO_SET0_PKEY),	"CMS_RecipientInfo_set0_pkey"},
{ERR_FUNC(CMS_F_CMS_SD_ASN1_CTRL),	"CMS_SD_ASN1_CTRL"},
{ERR_FUNC(CMS_F_CMS_SET1_SIGNERIDENTIFIER),	"cms_set1_SignerIdentifier"},
{ERR_FUNC(CMS_F_CMS_SET_DETACHED),	"CMS_set_detached"},
{ERR_FUNC(CMS_F_CMS_SIGN),	"CMS_sign"},
+5 −0
Original line number Diff line number Diff line
@@ -140,6 +140,9 @@ struct CMS_SignerInfo_st
	/* Signing certificate and key */
	X509 *signer;
	EVP_PKEY *pkey;
	/* Digest and public key context for alternative parameters */
	EVP_MD_CTX mctx;
	EVP_PKEY_CTX *pctx;
	};

struct CMS_SignerIdentifier_st
@@ -202,6 +205,8 @@ struct CMS_KeyTransRecipientInfo_st
	/* Recipient Key and cert */
	X509 *recip;
	EVP_PKEY *pkey;
	/* Public key context for this operation */
	EVP_PKEY_CTX *pctx;
	};

struct CMS_KeyAgreeRecipientInfo_st
Loading