Add function CMS_RecipientInfo_encrypt
[oweals/openssl.git] / crypto / cms / cms_env.c
index 1bea5582161497c5d486354e39e1dfb1969c7586..632dbae760affd481033e30f3a546f2cc68cf4b5 100644 (file)
 /* CMS EnvelopedData Utilities */
 
 DECLARE_ASN1_ITEM(CMS_EnvelopedData)
-DECLARE_ASN1_ITEM(CMS_RecipientInfo)
 DECLARE_ASN1_ITEM(CMS_KeyTransRecipientInfo)
 DECLARE_ASN1_ITEM(CMS_KEKRecipientInfo)
 DECLARE_ASN1_ITEM(CMS_OtherKeyAttribute)
 
 DECLARE_STACK_OF(CMS_RecipientInfo)
 
-static CMS_EnvelopedData *cms_get0_enveloped(CMS_ContentInfo *cms)
+CMS_EnvelopedData *cms_get0_enveloped(CMS_ContentInfo *cms)
        {
        if (OBJ_obj2nid(cms->contentType) != NID_pkcs7_enveloped)
                {
@@ -371,6 +370,8 @@ static int cms_RecipientInfo_ktri_decrypt(CMS_ContentInfo *cms,
        unsigned char *ek = NULL;
        size_t eklen;
        int ret = 0;
+       CMS_EncryptedContentInfo *ec;
+       ec = cms->d.envelopedData->encryptedContentInfo;
 
        if (ktri->pkey == NULL)
                {
@@ -417,8 +418,14 @@ static int cms_RecipientInfo_ktri_decrypt(CMS_ContentInfo *cms,
 
        ret = 1;
 
-       cms->d.envelopedData->encryptedContentInfo->key = ek;
-       cms->d.envelopedData->encryptedContentInfo->keylen = eklen;
+       if (ec->key)
+               {
+               OPENSSL_cleanse(ec->key, ec->keylen);
+               OPENSSL_free(ec->key);
+               }
+
+       ec->key = ek;
+       ec->keylen = eklen;
 
        err:
        if (pctx)
@@ -431,6 +438,24 @@ static int cms_RecipientInfo_ktri_decrypt(CMS_ContentInfo *cms,
 
 /* Key Encrypted Key (KEK) RecipientInfo routines */
 
+int CMS_RecipientInfo_kekri_id_cmp(CMS_RecipientInfo *ri, 
+                                       const unsigned char *id, size_t idlen)
+       {
+       ASN1_OCTET_STRING tmp_os;
+       CMS_KEKRecipientInfo *kekri;
+       if (ri->type != CMS_RECIPINFO_KEK)
+               {
+               CMSerr(CMS_F_CMS_RECIPIENTINFO_KEKRI_ID_CMP, CMS_R_NOT_KEK);
+               return -2;
+               }
+       kekri = ri->d.kekri;
+       tmp_os.type = V_ASN1_OCTET_STRING;
+       tmp_os.flags = 0;
+       tmp_os.data = (unsigned char *)id;
+       tmp_os.length = (int)idlen;
+       return ASN1_OCTET_STRING_cmp(&tmp_os, kekri->kekid->keyIdentifier);
+       }
+
 /* For now hard code AES key wrap info */
 
 static size_t aes_wrap_keylen(int nid)
@@ -600,25 +625,17 @@ int CMS_RecipientInfo_kekri_get0_id(CMS_RecipientInfo *ri,
        return 1;
        }
 
-
 int CMS_RecipientInfo_set0_key(CMS_RecipientInfo *ri, 
                                unsigned char *key, size_t keylen)
        {
        CMS_KEKRecipientInfo *kekri;
-       int wrap_nid;
        if (ri->type != CMS_RECIPINFO_KEK)
                {
                CMSerr(CMS_F_CMS_RECIPIENTINFO_SET0_KEY, CMS_R_NOT_KEK);
                return 0;
                }
+
        kekri = ri->d.kekri;
-       wrap_nid = OBJ_obj2nid(kekri->keyEncryptionAlgorithm->algorithm);
-       if (aes_wrap_keylen(wrap_nid) != keylen)
-               {
-               CMSerr(CMS_F_CMS_RECIPIENTINFO_SET0_KEY,
-                       CMS_R_INVALID_KEY_LENGTH);
-               return 0;
-               }
        kekri->key = key;
        kekri->keylen = keylen;
        return 1;
@@ -695,7 +712,7 @@ static int cms_RecipientInfo_kekri_decrypt(CMS_ContentInfo *cms,
        AES_KEY actx;
        unsigned char *ukey = NULL;
        int ukeylen;
-       int r = 0;
+       int r = 0, wrap_nid;
 
        ec = cms->d.envelopedData->encryptedContentInfo;
 
@@ -707,6 +724,14 @@ static int cms_RecipientInfo_kekri_decrypt(CMS_ContentInfo *cms,
                return 0;
                }
 
+       wrap_nid = OBJ_obj2nid(kekri->keyEncryptionAlgorithm->algorithm);
+       if (aes_wrap_keylen(wrap_nid) != kekri->keylen)
+               {
+               CMSerr(CMS_F_CMS_RECIPIENTINFO_KEKRI_DECRYPT,
+                       CMS_R_INVALID_KEY_LENGTH);
+               return 0;
+               }
+
        /* If encrypted key length is invalid don't bother */
 
        if (kekri->encryptedKey->length < 16)
@@ -768,6 +793,9 @@ int CMS_RecipientInfo_decrypt(CMS_ContentInfo *cms, CMS_RecipientInfo *ri)
                case CMS_RECIPINFO_KEK:
                return cms_RecipientInfo_kekri_decrypt(cms, ri);
 
+               case CMS_RECIPINFO_PASS:
+               return cms_RecipientInfo_pwri_crypt(cms, ri, 0);
+
                default:
                CMSerr(CMS_F_CMS_RECIPIENTINFO_DECRYPT,
                        CMS_R_UNSUPPORTED_RECPIENTINFO_TYPE);
@@ -775,12 +803,34 @@ int CMS_RecipientInfo_decrypt(CMS_ContentInfo *cms, CMS_RecipientInfo *ri)
                }
        }
 
+int CMS_RecipientInfo_encrypt(CMS_ContentInfo *cms, CMS_RecipientInfo *ri)
+       {
+       switch (ri->type)
+               {
+               case CMS_RECIPINFO_TRANS:
+               return cms_RecipientInfo_ktri_encrypt(cms, ri);
+
+               case CMS_RECIPINFO_KEK:
+               return cms_RecipientInfo_kekri_encrypt(cms, ri);
+               break;
+
+               case CMS_RECIPINFO_PASS:
+               return cms_RecipientInfo_pwri_crypt(cms, ri, 1);
+               break;
+
+               default:
+               CMSerr(CMS_F_CMS_RECIPIENTINFO_ENCRYPT,
+                               CMS_R_UNSUPPORTED_RECIPIENT_TYPE);
+               return 0;
+               }
+       }
+
 BIO *cms_EnvelopedData_init_bio(CMS_ContentInfo *cms)
        {
        CMS_EncryptedContentInfo *ec;
        STACK_OF(CMS_RecipientInfo) *rinfos;
        CMS_RecipientInfo *ri;
-       int i, r, ok = 0;
+       int i, ok = 0;
        BIO *ret;
 
        /* Get BIO first to set up key */
@@ -800,24 +850,7 @@ BIO *cms_EnvelopedData_init_bio(CMS_ContentInfo *cms)
        for (i = 0; i < sk_CMS_RecipientInfo_num(rinfos); i++)
                {
                ri = sk_CMS_RecipientInfo_value(rinfos, i);
-
-               switch (ri->type)
-                       {
-                       case CMS_RECIPINFO_TRANS:
-                       r = cms_RecipientInfo_ktri_encrypt(cms, ri);
-                       break;
-
-                       case CMS_RECIPINFO_KEK:
-                       r = cms_RecipientInfo_kekri_encrypt(cms, ri);
-                       break;
-
-                       default:
-                       CMSerr(CMS_F_CMS_ENVELOPEDDATA_INIT_BIO,
-                               CMS_R_UNSUPPORTED_RECIPIENT_TYPE);
-                       goto err;
-                       }
-
-               if (r <= 0)
+               if (CMS_RecipientInfo_encrypt(cms, ri) <= 0)
                        {
                        CMSerr(CMS_F_CMS_ENVELOPEDDATA_INIT_BIO,
                                CMS_R_ERROR_SETTING_RECIPIENTINFO);