#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);
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);
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);
#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
#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
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;
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;
CMS_KeyTransRecipientInfo *ktri;
CMS_EnvelopedData *env;
EVP_PKEY *pk = NULL;
- int i, type;
+ int type;
env = cms_get0_enveloped(cms);
if (!env)
goto err;
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;
{
CMS_KeyTransRecipientInfo *ktri;
CMS_EncryptedContentInfo *ec;
- EVP_PKEY_CTX *pctx = NULL;
+ EVP_PKEY_CTX *pctx;
unsigned char *ek = NULL;
size_t eklen;
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)
err:
if (pctx)
+ {
EVP_PKEY_CTX_free(pctx);
+ ktri->pctx = NULL;
+ }
if (ek)
OPENSSL_free(ek);
return ret;
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;
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;
goto err;
}
- if (EVP_PKEY_decrypt(pctx, ek, &eklen,
+ if (EVP_PKEY_decrypt(ktri->pctx, ek, &eklen,
ktri->encryptedKey->data,
ktri->encryptedKey->length) <= 0)
{
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);
return -1;
}
+static int cms_sd_asn1_ctrl(CMS_SignerInfo *si, int cmd)
+ {
+ EVP_PKEY *pkey = si->pkey;
+ int i;
+ if (!pkey->ameth || !pkey->ameth->pkey_ctrl)
+ return 1;
+ i = pkey->ameth->pkey_ctrl(pkey, ASN1_PKEY_CTRL_CMS_SIGN, cmd, si);
+ if (i == -2)
+ {
+ CMSerr(CMS_F_CMS_SD_ASN1_CTRL,
+ CMS_R_NOT_SUPPORTED_FOR_THIS_KEY_TYPE);
+ return 0;
+ }
+ if (i <= 0)
+ {
+ CMSerr(CMS_F_CMS_SD_ASN1_CTRL, CMS_R_CTRL_FAILURE);
+ return 0;
+ }
+ return 1;
+ }
+
CMS_SignerInfo *CMS_add1_signer(CMS_ContentInfo *cms,
X509 *signer, EVP_PKEY *pk, const EVP_MD *md,
unsigned int flags)
si->pkey = pk;
si->signer = signer;
+ EVP_MD_CTX_init(&si->mctx);
+ si->pctx = NULL;
if (flags & CMS_USE_KEYID)
{
}
}
- if (pk->ameth && pk->ameth->pkey_ctrl)
- {
- i = pk->ameth->pkey_ctrl(pk, ASN1_PKEY_CTRL_CMS_SIGN,
- 0, si);
- if (i == -2)
- {
- CMSerr(CMS_F_CMS_ADD1_SIGNER,
- CMS_R_NOT_SUPPORTED_FOR_THIS_KEY_TYPE);
- goto err;
- }
- if (i <= 0)
- {
- CMSerr(CMS_F_CMS_ADD1_SIGNER, CMS_R_CTRL_FAILURE);
- goto err;
- }
- }
-
+ if (!(flags & CMS_KEY_PARAM) && !cms_sd_asn1_ctrl(si, 0))
+ goto err;
if (!(flags & CMS_NOATTR))
{
/* Initialialize signed attributes strutucture so other
{
if (!cms_copy_messageDigest(cms, si))
goto err;
- if (!(flags & CMS_PARTIAL) &&
+ if (!(flags & (CMS_PARTIAL|CMS_KEY_PARAM)) &&
!CMS_SignerInfo_sign(si))
goto err;
}
goto merr;
}
+ if (flags & CMS_KEY_PARAM)
+ {
+ if (flags & CMS_NOATTR)
+ {
+ si->pctx = EVP_PKEY_CTX_new(si->pkey, NULL);
+ if (!si->pctx)
+ goto err;
+ if (EVP_PKEY_sign_init(si->pctx) <= 0)
+ goto err;
+ if (EVP_PKEY_CTX_set_signature_md(si->pctx, md) <= 0)
+ goto err;
+ }
+ else if (EVP_DigestSignInit(&si->mctx, &si->pctx, md, NULL, pk) <= 0)
+ goto err;
+ }
+
if (!sd->signerInfos)
sd->signerInfos = sk_CMS_SignerInfo_new_null();
if (!sd->signerInfos ||
}
+EVP_PKEY_CTX *CMS_SignerInfo_get0_pkey_ctx(CMS_SignerInfo *si)
+ {
+ return si->pctx;
+ }
+
+EVP_MD_CTX *CMS_SignerInfo_get0_md_ctx(CMS_SignerInfo *si)
+ {
+ return &si->mctx;
+ }
+
STACK_OF(CMS_SignerInfo) *CMS_get0_SignerInfos(CMS_ContentInfo *cms)
{
CMS_SignedData *sd;
{
EVP_MD_CTX mctx;
int r = 0;
+ EVP_PKEY_CTX *pctx = NULL;
EVP_MD_CTX_init(&mctx);
-
if (!si->pkey)
{
CMSerr(CMS_F_CMS_SIGNERINFO_CONTENT_SIGN, CMS_R_NO_PRIVATE_KEY);
if (!cms_DigestAlgorithm_find_ctx(&mctx, chain, si->digestAlgorithm))
goto err;
+ /* Set SignerInfo algortihm details if we used custom parametsr */
+ if (si->pctx && !cms_sd_asn1_ctrl(si, 0))
+ goto err;
/* If any signed attributes calculate and add messageDigest attribute */
if (!CMS_SignerInfo_sign(si))
goto err;
}
+ else if (si->pctx)
+ {
+ unsigned char *sig;
+ size_t siglen;
+ unsigned char md[EVP_MAX_MD_SIZE];
+ unsigned int mdlen;
+ pctx = si->pctx;
+ if (!EVP_DigestFinal_ex(&mctx, md, &mdlen))
+ goto err;
+ sig = OPENSSL_malloc(EVP_PKEY_size(si->pkey));
+ if (!sig)
+ {
+ CMSerr(CMS_F_CMS_SIGNERINFO_CONTENT_SIGN,
+ ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ if (EVP_PKEY_sign(pctx, sig, &siglen, md, mdlen) <= 0)
+ goto err;
+ ASN1_STRING_set0(si->signature, sig, siglen);
+ }
else
{
unsigned char *sig;
err:
EVP_MD_CTX_cleanup(&mctx);
+ if (pctx)
+ EVP_PKEY_CTX_free(pctx);
return r;
}
int CMS_SignerInfo_sign(CMS_SignerInfo *si)
{
- EVP_MD_CTX mctx;
+ EVP_MD_CTX *mctx = &si->mctx;
EVP_PKEY_CTX *pctx;
unsigned char *abuf = NULL;
int alen;
if (md == NULL)
return 0;
- EVP_MD_CTX_init(&mctx);
if (CMS_signed_get_attr_by_NID(si, NID_pkcs9_signingTime, -1) < 0)
{
goto err;
}
- if (EVP_DigestSignInit(&mctx, &pctx, md, NULL, si->pkey) <= 0)
- goto err;
+ if (si->pctx)
+ pctx = si->pctx;
+ else
+ {
+ EVP_MD_CTX_init(mctx);
+ if (EVP_DigestSignInit(mctx, &pctx, md, NULL, si->pkey) <= 0)
+ goto err;
+ }
if (EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_SIGN,
EVP_PKEY_CTRL_CMS_SIGN, 0, si) <= 0)
ASN1_ITEM_rptr(CMS_Attributes_Sign));
if(!abuf)
goto err;
- if (EVP_DigestSignUpdate(&mctx, abuf, alen) <= 0)
+ if (EVP_DigestSignUpdate(mctx, abuf, alen) <= 0)
goto err;
- if (EVP_DigestSignFinal(&mctx, NULL, &siglen) <= 0)
+ if (EVP_DigestSignFinal(mctx, NULL, &siglen) <= 0)
goto err;
OPENSSL_free(abuf);
abuf = OPENSSL_malloc(siglen);
if(!abuf)
goto err;
- if (EVP_DigestSignFinal(&mctx, abuf, &siglen) <= 0)
+ if (EVP_DigestSignFinal(mctx, abuf, &siglen) <= 0)
goto err;
if (EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_SIGN,
goto err;
}
- EVP_MD_CTX_cleanup(&mctx);
+ EVP_MD_CTX_cleanup(mctx);
ASN1_STRING_set0(si->signature, abuf, siglen);
err:
if (abuf)
OPENSSL_free(abuf);
- EVP_MD_CTX_cleanup(&mctx);
+ EVP_MD_CTX_cleanup(mctx);
return 0;
}
int CMS_SignerInfo_verify(CMS_SignerInfo *si)
{
- EVP_MD_CTX mctx;
- EVP_PKEY_CTX *pctx;
+ EVP_MD_CTX *mctx = &si->mctx;
unsigned char *abuf = NULL;
int alen, r = -1;
const EVP_MD *md = NULL;
md = EVP_get_digestbyobj(si->digestAlgorithm->algorithm);
if (md == NULL)
return -1;
- EVP_MD_CTX_init(&mctx);
- if (EVP_DigestVerifyInit(&mctx, &pctx, md, NULL, si->pkey) <= 0)
+ EVP_MD_CTX_init(mctx);
+ if (EVP_DigestVerifyInit(mctx, &si->pctx, md, NULL, si->pkey) <= 0)
+ goto err;
+
+ if (!cms_sd_asn1_ctrl(si, 1))
goto err;
alen = ASN1_item_i2d((ASN1_VALUE *)si->signedAttrs,&abuf,
ASN1_ITEM_rptr(CMS_Attributes_Verify));
if(!abuf)
goto err;
- r = EVP_DigestVerifyUpdate(&mctx, abuf, alen);
+ r = EVP_DigestVerifyUpdate(mctx, abuf, alen);
OPENSSL_free(abuf);
if (r <= 0)
{
r = -1;
goto err;
}
- r = EVP_DigestVerifyFinal(&mctx,
+ r = EVP_DigestVerifyFinal(mctx,
si->signature->data, si->signature->length);
if (r <= 0)
CMSerr(CMS_F_CMS_SIGNERINFO_VERIFY, CMS_R_VERIFICATION_FAILURE);
err:
- EVP_MD_CTX_cleanup(&mctx);
+ EVP_MD_CTX_cleanup(mctx);
return r;
}
{
ASN1_OCTET_STRING *os = NULL;
EVP_MD_CTX mctx;
+ EVP_PKEY_CTX *pkctx = NULL;
int r = -1;
+ unsigned char mval[EVP_MAX_MD_SIZE];
+ unsigned int mlen;
EVP_MD_CTX_init(&mctx);
/* If we have any signed attributes look for messageDigest value */
if (CMS_signed_get_attr_count(si) >= 0)
if (!cms_DigestAlgorithm_find_ctx(&mctx, chain, si->digestAlgorithm))
goto err;
+ if (EVP_DigestFinal_ex(&mctx, mval, &mlen) <= 0)
+ {
+ CMSerr(CMS_F_CMS_SIGNERINFO_VERIFY_CONTENT,
+ CMS_R_UNABLE_TO_FINALIZE_CONTEXT);
+ goto err;
+ }
+
/* If messageDigest found compare it */
if (os)
{
- unsigned char mval[EVP_MAX_MD_SIZE];
- unsigned int mlen;
- if (EVP_DigestFinal_ex(&mctx, mval, &mlen) <= 0)
- {
- CMSerr(CMS_F_CMS_SIGNERINFO_VERIFY_CONTENT,
- CMS_R_UNABLE_TO_FINALIZE_CONTEXT);
- goto err;
- }
if (mlen != (unsigned int)os->length)
{
CMSerr(CMS_F_CMS_SIGNERINFO_VERIFY_CONTENT,
}
else
{
- r = EVP_VerifyFinal(&mctx, si->signature->data,
- si->signature->length, si->pkey);
+ const EVP_MD *md = EVP_MD_CTX_md(&mctx);
+ pkctx = EVP_PKEY_CTX_new(si->pkey, NULL);
+ if (EVP_PKEY_verify_init(pkctx) <= 0)
+ goto err;
+ if (EVP_PKEY_CTX_set_signature_md(pkctx, md) <= 0)
+ goto err;
+ si->pctx = pkctx;
+ if (!cms_sd_asn1_ctrl(si, 1))
+ goto err;
+ r = EVP_PKEY_verify(pkctx, si->signature->data,
+ si->signature->length,
+ mval, mlen);
if (r <= 0)
{
CMSerr(CMS_F_CMS_SIGNERINFO_VERIFY_CONTENT,
}
err:
+ if (pkctx)
+ EVP_PKEY_CTX_free(pkctx);
EVP_MD_CTX_cleanup(&mctx);
return r;