Add KDF for DH.
[openssl.git] / crypto / cms / cms_asn1.c
index 918dd0f30c7c16a48e843342f830753d4b2d6222..83ae2cc0f3bd223325d107cd8c81846bc0465390 100644 (file)
@@ -53,6 +53,7 @@
 
 #include <openssl/asn1t.h>
 #include <openssl/pem.h>
+#include <openssl/x509v3.h>
 #include "cms.h"
 #include "cms_lcl.h"
 
@@ -96,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;
        }
@@ -130,8 +133,8 @@ ASN1_NDEF_SEQUENCE(CMS_SignedData) = {
 } ASN1_NDEF_SEQUENCE_END(CMS_SignedData)
 
 ASN1_SEQUENCE(CMS_OriginatorInfo) = {
-       ASN1_IMP_SET_OF_OPT(CMS_SignedData, certificates, CMS_CertificateChoices, 0),
-       ASN1_IMP_SET_OF_OPT(CMS_SignedData, crls, CMS_RevocationInfoChoice, 1)
+       ASN1_IMP_SET_OF_OPT(CMS_OriginatorInfo, certificates, CMS_CertificateChoices, 0),
+       ASN1_IMP_SET_OF_OPT(CMS_OriginatorInfo, crls, CMS_RevocationInfoChoice, 1)
 } ASN1_SEQUENCE_END(CMS_OriginatorInfo)
 
 ASN1_NDEF_SEQUENCE(CMS_EncryptedContentInfo) = {
@@ -163,10 +166,22 @@ ASN1_CHOICE(CMS_KeyAgreeRecipientIdentifier) = {
   ASN1_IMP(CMS_KeyAgreeRecipientIdentifier, d.rKeyId, CMS_RecipientKeyIdentifier, 0)
 } ASN1_CHOICE_END(CMS_KeyAgreeRecipientIdentifier)
 
-ASN1_SEQUENCE(CMS_RecipientEncryptedKey) = {
+static int cms_rek_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
+                                                       void *exarg)
+       {
+       CMS_RecipientEncryptedKey *rek = (CMS_RecipientEncryptedKey *)*pval;
+       if(operation == ASN1_OP_FREE_POST)
+               {
+               if (rek->pkey)
+                       EVP_PKEY_free(rek->pkey);
+               }
+       return 1;
+       }
+
+ASN1_SEQUENCE_cb(CMS_RecipientEncryptedKey, cms_rek_cb) = {
        ASN1_SIMPLE(CMS_RecipientEncryptedKey, rid, CMS_KeyAgreeRecipientIdentifier),
        ASN1_SIMPLE(CMS_RecipientEncryptedKey, encryptedKey, ASN1_OCTET_STRING)
-} ASN1_SEQUENCE_END(CMS_RecipientEncryptedKey)
+} ASN1_SEQUENCE_END_cb(CMS_RecipientEncryptedKey, CMS_RecipientEncryptedKey)
 
 ASN1_SEQUENCE(CMS_OriginatorPublicKey) = {
   ASN1_SIMPLE(CMS_OriginatorPublicKey, algorithm, X509_ALGOR),
@@ -179,13 +194,33 @@ ASN1_CHOICE(CMS_OriginatorIdentifierOrKey) = {
   ASN1_IMP(CMS_OriginatorIdentifierOrKey, d.originatorKey, CMS_OriginatorPublicKey, 1)
 } ASN1_CHOICE_END(CMS_OriginatorIdentifierOrKey)
 
-ASN1_SEQUENCE(CMS_KeyAgreeRecipientInfo) = {
+static int cms_kari_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
+                                                       void *exarg)
+       {
+       CMS_KeyAgreeRecipientInfo *kari = (CMS_KeyAgreeRecipientInfo *)*pval;
+       if(operation == ASN1_OP_NEW_POST)
+               {
+               EVP_CIPHER_CTX_init(&kari->ctx);
+               EVP_CIPHER_CTX_set_flags(&kari->ctx,
+                                       EVP_CIPHER_CTX_FLAG_WRAP_ALLOW);
+               kari->pctx = NULL;
+               }
+       else if(operation == ASN1_OP_FREE_POST)
+               {
+               if (kari->pctx)
+                       EVP_PKEY_CTX_free(kari->pctx);
+               EVP_CIPHER_CTX_cleanup(&kari->ctx);
+               }
+       return 1;
+       }
+
+ASN1_SEQUENCE_cb(CMS_KeyAgreeRecipientInfo, cms_kari_cb) = {
        ASN1_SIMPLE(CMS_KeyAgreeRecipientInfo, version, LONG),
        ASN1_EXP(CMS_KeyAgreeRecipientInfo, originator, CMS_OriginatorIdentifierOrKey, 0),
        ASN1_EXP_OPT(CMS_KeyAgreeRecipientInfo, ukm, ASN1_OCTET_STRING, 1),
        ASN1_SIMPLE(CMS_KeyAgreeRecipientInfo, keyEncryptionAlgorithm, X509_ALGOR),
        ASN1_SEQUENCE_OF(CMS_KeyAgreeRecipientInfo, recipientEncryptedKeys, CMS_RecipientEncryptedKey)
-} ASN1_SEQUENCE_END(CMS_KeyAgreeRecipientInfo)
+} ASN1_SEQUENCE_END_cb(CMS_KeyAgreeRecipientInfo, CMS_KeyAgreeRecipientInfo)
 
 ASN1_SEQUENCE(CMS_KEKIdentifier) = {
        ASN1_SIMPLE(CMS_KEKIdentifier, keyIdentifier, ASN1_OCTET_STRING),
@@ -216,7 +251,7 @@ ASN1_SEQUENCE(CMS_OtherRecipientInfo) = {
 static int cms_ri_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
                                                        void *exarg)
        {
-       if(operation == ASN1_OP_FREE_POST)
+       if(operation == ASN1_OP_FREE_PRE)
                {
                CMS_RecipientInfo *ri = (CMS_RecipientInfo *)*pval;
                if (ri->type == CMS_RECIPINFO_TRANS)
@@ -226,6 +261,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)
                        {
@@ -236,6 +273,15 @@ static int cms_ri_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
                                OPENSSL_free(kekri->key);
                                }
                        }
+               else if (ri->type == CMS_RECIPINFO_PASS)
+                       {
+                       CMS_PasswordRecipientInfo *pwri = ri->d.pwri;
+                       if (pwri->pass)
+                               {
+                               OPENSSL_cleanse(pwri->pass, pwri->passlen);
+                               OPENSSL_free(pwri->pass);
+                               }
+                       }
                }
        return 1;
        }
@@ -306,9 +352,11 @@ static int cms_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
                                                        void *exarg)
        {
        ASN1_STREAM_ARG *sarg = exarg;
-       CMS_ContentInfo *cms;
+       CMS_ContentInfo *cms = NULL;
        if (pval)
                cms = (CMS_ContentInfo *)*pval;
+       else
+               return 1;
        switch(operation)
                {
 
@@ -355,3 +403,66 @@ ASN1_ITEM_TEMPLATE(CMS_Attributes_Verify) =
                                V_ASN1_SET, CMS_ATTRIBUTES, X509_ATTRIBUTE)
 ASN1_ITEM_TEMPLATE_END(CMS_Attributes_Verify)
 
+
+
+ASN1_CHOICE(CMS_ReceiptsFrom) = {
+  ASN1_IMP(CMS_ReceiptsFrom, d.allOrFirstTier, LONG, 0),
+  ASN1_IMP_SEQUENCE_OF(CMS_ReceiptsFrom, d.receiptList, GENERAL_NAMES, 1)
+} ASN1_CHOICE_END(CMS_ReceiptsFrom)
+
+ASN1_SEQUENCE(CMS_ReceiptRequest) = {
+  ASN1_SIMPLE(CMS_ReceiptRequest, signedContentIdentifier, ASN1_OCTET_STRING),
+  ASN1_SIMPLE(CMS_ReceiptRequest, receiptsFrom, CMS_ReceiptsFrom),
+  ASN1_SEQUENCE_OF(CMS_ReceiptRequest, receiptsTo, GENERAL_NAMES)
+} ASN1_SEQUENCE_END(CMS_ReceiptRequest)
+
+ASN1_SEQUENCE(CMS_Receipt) = {
+  ASN1_SIMPLE(CMS_Receipt, version, LONG),
+  ASN1_SIMPLE(CMS_Receipt, contentType, ASN1_OBJECT),
+  ASN1_SIMPLE(CMS_Receipt, signedContentIdentifier, ASN1_OCTET_STRING),
+  ASN1_SIMPLE(CMS_Receipt, originatorSignatureValue, ASN1_OCTET_STRING)
+} ASN1_SEQUENCE_END(CMS_Receipt)
+
+/* Utilities to encode the CMS_SharedInfo structure used during key
+ * derivation.
+ */
+
+typedef struct {
+       X509_ALGOR *keyInfo;
+       ASN1_OCTET_STRING *entityUInfo;
+       ASN1_OCTET_STRING *suppPubInfo;
+} CMS_SharedInfo;
+
+ASN1_SEQUENCE(CMS_SharedInfo) = {
+  ASN1_SIMPLE(CMS_SharedInfo, keyInfo, X509_ALGOR),
+  ASN1_EXP_OPT(CMS_SharedInfo, entityUInfo, ASN1_OCTET_STRING, 0),
+  ASN1_EXP_OPT(CMS_SharedInfo, suppPubInfo, ASN1_OCTET_STRING, 2),
+} ASN1_SEQUENCE_END(CMS_SharedInfo)
+
+int CMS_SharedInfo_encode(unsigned char **pder, X509_ALGOR *kekalg, 
+                       ASN1_OCTET_STRING *ukm, int keylen)
+       {
+       union {
+               CMS_SharedInfo *pecsi;
+               ASN1_VALUE *a;
+       } intsi = {NULL};
+
+       ASN1_OCTET_STRING oklen;
+       unsigned char kl[4];
+       CMS_SharedInfo ecsi;
+
+       keylen <<= 3;
+       kl[0] = (keylen >> 24) & 0xff;
+       kl[1] = (keylen >> 16) & 0xff;
+       kl[2] = (keylen >> 8) & 0xff;
+       kl[3] = keylen & 0xff;
+       oklen.length = 4;
+       oklen.data = kl;
+       oklen.type = V_ASN1_OCTET_STRING;
+       oklen.flags = 0;
+       ecsi.keyInfo = kekalg;
+       ecsi.entityUInfo = ukm;
+       ecsi.suppPubInfo = &oklen;
+       intsi.pecsi = &ecsi;
+       return ASN1_item_i2d(intsi.a, pder, ASN1_ITEM_rptr(CMS_SharedInfo));
+       }