Skip to content

Commit

Permalink
CMS public key parameter support.
Browse files Browse the repository at this point in the history
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.
(cherry picked from commit e365352)
  • Loading branch information
snhenson committed Oct 1, 2013
1 parent d6dc5c5 commit f2edf31
Show file tree
Hide file tree
Showing 6 changed files with 212 additions and 75 deletions.
6 changes: 6 additions & 0 deletions crypto/cms/cms.h
Expand Up @@ -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);

Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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
Expand All @@ -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
Expand Down
4 changes: 4 additions & 0 deletions crypto/cms/cms_asn1.c
Expand Up @@ -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;
}
Expand Down Expand Up @@ -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)
{
Expand Down
100 changes: 70 additions & 30 deletions crypto/cms/cms_env.c
Expand Up @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);
goto err;
}
}
else if (!cms_env_asn1_ctrl(ri, 0))
goto err;

if (!sk_CMS_RecipientInfo_push(env->recipientInfos, ri))
goto merr;
Expand Down Expand Up @@ -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;

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

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

if (EVP_PKEY_encrypt_init(pctx) <= 0)
goto err;
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)
Expand Down Expand Up @@ -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;
Expand All @@ -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;
Expand All @@ -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 (!cms_env_asn1_ctrl(ri, 1))
goto err;

if (EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_DECRYPT,
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;
Expand All @@ -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)
{
Expand All @@ -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);

Expand Down
2 changes: 2 additions & 0 deletions crypto/cms/cms_err.c
Expand Up @@ -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"},
Expand All @@ -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"},
Expand Down
5 changes: 5 additions & 0 deletions crypto/cms/cms_lcl.h
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down

0 comments on commit f2edf31

Please sign in to comment.