New utility functions for encryptedData content type which will also be used
authorDr. Stephen Henson <steve@openssl.org>
Fri, 14 Mar 2008 00:58:43 +0000 (00:58 +0000)
committerDr. Stephen Henson <steve@openssl.org>
Fri, 14 Mar 2008 00:58:43 +0000 (00:58 +0000)
by envelopedData.

Use PRE and not POST when freeing up RecipientInfo.

crypto/cms/Makefile
crypto/cms/cms.h
crypto/cms/cms_asn1.c
crypto/cms/cms_enc.c [new file with mode: 0644]
crypto/cms/cms_env.c
crypto/cms/cms_err.c
test/runex.pl

index fdca7fe..abb8d83 100644 (file)
@@ -18,9 +18,9 @@ APPS=
 
 LIB=$(TOP)/libcrypto.a
 LIBSRC= cms_lib.c cms_asn1.c cms_att.c cms_io.c cms_smime.c cms_err.c \
-       cms_sd.c cms_dd.c cms_cd.c cms_env.c
+       cms_sd.c cms_dd.c cms_cd.c cms_env.c cms_enc.c
 LIBOBJ= cms_lib.o cms_asn1.o cms_att.o cms_io.o cms_smime.o cms_err.o \
-       cms_sd.o cms_dd.o cms_cd.o cms_env.o
+       cms_sd.o cms_dd.o cms_cd.o cms_env.o cms_enc.o
 
 SRC= $(LIBSRC)
 
index 2f45f57..0df4b0f 100644 (file)
@@ -241,6 +241,7 @@ void ERR_load_CMS_strings(void);
 #define CMS_F_CMS_ADD1_RECIPIENT_CERT                   99
 #define CMS_F_CMS_ADD1_SIGNER                           100
 #define CMS_F_CMS_ADD1_SIGNINGTIME                      101
+#define CMS_F_CMS_BIO_TO_ENCRYPTEDCONTENT               137
 #define CMS_F_CMS_COMPRESS                              102
 #define CMS_F_CMS_COMPRESSEDDATA_CREATE                         103
 #define CMS_F_CMS_COMPRESSEDDATA_INIT_BIO               104
@@ -253,6 +254,7 @@ void ERR_load_CMS_strings(void);
 #define CMS_F_CMS_DIGESTALGORITHM_INIT_BIO              111
 #define CMS_F_CMS_DIGESTEDDATA_DO_FINAL                         112
 #define CMS_F_CMS_DIGEST_VERIFY                                 113
+#define CMS_F_CMS_ENCRYPTEDCONTENT_TO_BIO               138
 #define CMS_F_CMS_ENVELOPED_DATA_INIT                   114
 #define CMS_F_CMS_FINAL                                         115
 #define CMS_F_CMS_GET0_CERTIFICATE_CHOICES              116
@@ -280,6 +282,8 @@ void ERR_load_CMS_strings(void);
 /* Reason codes. */
 #define CMS_R_ADD_SIGNER_ERROR                          99
 #define CMS_R_CERTIFICATE_VERIFY_ERROR                  100
+#define CMS_R_CIPHER_INITIALISATION_ERROR               138
+#define CMS_R_CIPHER_PARAMETER_INITIALISATION_ERROR     139
 #define CMS_R_CMS_DATAFINAL_ERROR                       101
 #define CMS_R_CONTENT_NOT_FOUND                                 102
 #define CMS_R_CONTENT_TYPE_NOT_COMPRESSED_DATA          103
@@ -290,6 +294,7 @@ void ERR_load_CMS_strings(void);
 #define CMS_R_CTRL_FAILURE                              108
 #define CMS_R_ERROR_GETTING_PUBLIC_KEY                  109
 #define CMS_R_ERROR_READING_MESSAGEDIGEST_ATTRIBUTE     110
+#define CMS_R_INVALID_KEY_LENGTH                        140
 #define CMS_R_MD_BIO_INIT_ERROR                                 111
 #define CMS_R_MESSAGEDIGEST_ATTRIBUTE_WRONG_LENGTH      112
 #define CMS_R_MESSAGEDIGEST_WRONG_LENGTH                113
@@ -311,6 +316,7 @@ void ERR_load_CMS_strings(void);
 #define CMS_R_TYPE_NOT_DATA                             129
 #define CMS_R_TYPE_NOT_DIGESTED_DATA                    130
 #define CMS_R_UNABLE_TO_FINALIZE_CONTEXT                131
+#define CMS_R_UNKNOWN_CIPHER                            141
 #define CMS_R_UNKNOWN_DIGEST_ALGORIHM                   132
 #define CMS_R_UNKNOWN_ID                                133
 #define CMS_R_UNSUPPORTED_COMPRESSION_ALGORITHM                 134
index 918dd0f..b9521c9 100644 (file)
@@ -216,7 +216,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)
diff --git a/crypto/cms/cms_enc.c b/crypto/cms/cms_enc.c
new file mode 100644 (file)
index 0000000..084bc12
--- /dev/null
@@ -0,0 +1,196 @@
+/* crypto/cms/cms_enc.c */
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
+ * project.
+ */
+/* ====================================================================
+ * Copyright (c) 2008 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer. 
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ */
+
+#include "cryptlib.h"
+#include <openssl/asn1t.h>
+#include <openssl/pem.h>
+#include <openssl/x509v3.h>
+#include <openssl/err.h>
+#include <openssl/cms.h>
+#include <openssl/rand.h>
+#include "cms_lcl.h"
+#include "asn1_locl.h"
+
+/* CMS EncryptedData Utilities */
+
+/* Set up EncryptedContentInfo based on supplied cipher bio */
+
+int cms_bio_to_EncryptedContent(CMS_EncryptedContentInfo *ec,
+                                       const unsigned char *key, int keylen,
+                                       BIO *b)
+       {
+       EVP_CIPHER_CTX *ctx = NULL;
+       unsigned char iv[EVP_MAX_IV_LENGTH], *piv;
+       int ivlen;
+
+       BIO_get_cipher_ctx(b, &ctx);
+
+       /* If necessary set key length */
+
+       if (keylen != EVP_CIPHER_CTX_key_length(ctx))
+               {
+               if (EVP_CIPHER_CTX_set_key_length(ctx, keylen) <= 0)
+                       {
+                       CMSerr(CMS_F_CMS_BIO_TO_ENCRYPTEDCONTENT,
+                               CMS_R_INVALID_KEY_LENGTH);
+                       return 0;
+                       }
+               }
+
+       /* Generate a random IV if we need one */
+
+       ivlen = EVP_CIPHER_CTX_iv_length(ctx);
+       if (ivlen > 0)
+               {
+               if (RAND_pseudo_bytes(iv, ivlen) <= 0)
+                       return 0;
+               piv = iv;
+               }
+       else
+               piv = NULL;
+
+       if (EVP_CipherInit_ex(ctx, NULL, NULL, key, piv, 1) <= 0)
+               {
+               CMSerr(CMS_F_CMS_BIO_TO_ENCRYPTEDCONTENT,
+                               CMS_R_CIPHER_INITIALISATION_ERROR);
+               return 0;
+               }
+
+       ec->contentEncryptionAlgorithm->algorithm =
+                       OBJ_nid2obj(EVP_CIPHER_CTX_type(ctx));
+
+       if (piv)
+               {
+               ec->contentEncryptionAlgorithm->parameter = ASN1_TYPE_new();
+               if (!ec->contentEncryptionAlgorithm->parameter)
+                       {
+                       CMSerr(CMS_F_CMS_BIO_TO_ENCRYPTEDCONTENT,
+                                                       ERR_R_MALLOC_FAILURE);
+                       return 0;
+                       }
+               if (EVP_CIPHER_param_to_asn1(ctx, 
+                       ec->contentEncryptionAlgorithm->parameter) <= 0)
+                       {
+                       CMSerr(CMS_F_CMS_BIO_TO_ENCRYPTEDCONTENT,
+                               CMS_R_CIPHER_PARAMETER_INITIALISATION_ERROR);
+                       return 0;
+                       }
+               }
+
+       return 1;
+       }
+
+/* Return BIO based on EncryptedContentInfo and key */
+
+BIO *cms_EncryptedContent_to_bio(CMS_EncryptedContentInfo *ec,
+                                       const unsigned char *key, int keylen)
+       {
+       BIO *b;
+       EVP_CIPHER_CTX *ctx;
+       const EVP_CIPHER *ciph;
+       b = BIO_new(BIO_f_cipher());
+       if (!b)
+               {
+               CMSerr(CMS_F_CMS_ENCRYPTEDCONTENT_TO_BIO, ERR_R_MALLOC_FAILURE);
+               return NULL;
+               }
+       BIO_get_cipher_ctx(b, &ctx);
+
+       ciph = EVP_get_cipherbyobj(ec->contentEncryptionAlgorithm->algorithm);
+
+       if (!ciph)
+               {
+               CMSerr(CMS_F_CMS_ENCRYPTEDCONTENT_TO_BIO, CMS_R_UNKNOWN_CIPHER);
+               goto err;
+               }
+
+       if (EVP_CipherInit_ex(ctx, ciph, NULL, NULL, NULL, 0) <= 0)
+               {
+               CMSerr(CMS_F_CMS_ENCRYPTEDCONTENT_TO_BIO,
+                               CMS_R_CIPHER_INITIALISATION_ERROR);
+               goto err;
+               }
+
+       /* If necessary set key length */
+
+       if (keylen != EVP_CIPHER_CTX_key_length(ctx))
+               {
+               if (EVP_CIPHER_CTX_set_key_length(ctx, keylen) <= 0)
+                       {
+                       CMSerr(CMS_F_CMS_ENCRYPTEDCONTENT_TO_BIO,
+                               CMS_R_INVALID_KEY_LENGTH);
+                       goto err;
+                       }
+               }
+
+       if (EVP_CipherInit_ex(ctx, NULL, NULL, key, NULL, 0) <= 0)
+               {
+               CMSerr(CMS_F_CMS_ENCRYPTEDCONTENT_TO_BIO,
+                               CMS_R_CIPHER_INITIALISATION_ERROR);
+               goto err;
+               }
+
+       if (EVP_CIPHER_asn1_to_param(ctx, 
+                       ec->contentEncryptionAlgorithm->parameter) <= 0)
+                       {
+                       CMSerr(CMS_F_CMS_ENCRYPTEDCONTENT_TO_BIO,
+                               CMS_R_CIPHER_PARAMETER_INITIALISATION_ERROR);
+                       goto err;
+                       }
+       return b;
+
+       err:
+       BIO_free(b);
+       return NULL;
+       }
+
index 2381985..3a5991e 100644 (file)
@@ -57,6 +57,7 @@
 #include <openssl/x509v3.h>
 #include <openssl/err.h>
 #include <openssl/cms.h>
+#include <openssl/rand.h>
 #include "cms_lcl.h"
 #include "asn1_locl.h"
 
@@ -66,12 +67,6 @@ DECLARE_ASN1_ITEM(CMS_EnvelopedData)
 DECLARE_ASN1_ITEM(CMS_RecipientInfo)
 DECLARE_ASN1_ITEM(CMS_KeyTransRecipientInfo)
 
-#if 0
-IMPLEMENT_ASN1_ALLOC_FUNCTIONS(CMS_EnvelopedData)
-IMPLEMENT_ASN1_ALLOC_FUNCTIONS(CMS_RecipientInfo)
-IMPLEMENT_ASN1_ALLOC_FUNCTIONS(CMS_KeyTransRecipientInfo)
-#endif
-
 DECLARE_STACK_OF(CMS_RecipientInfo)
 
 static CMS_EnvelopedData *cms_get0_enveloped(CMS_ContentInfo *cms)
index a2c7c1b..8a45c05 100644 (file)
@@ -73,6 +73,7 @@ static ERR_STRING_DATA CMS_str_functs[]=
 {ERR_FUNC(CMS_F_CMS_ADD1_RECIPIENT_CERT),      "CMS_ADD1_RECIPIENT_CERT"},
 {ERR_FUNC(CMS_F_CMS_ADD1_SIGNER),      "CMS_add1_signer"},
 {ERR_FUNC(CMS_F_CMS_ADD1_SIGNINGTIME), "CMS_ADD1_SIGNINGTIME"},
+{ERR_FUNC(CMS_F_CMS_BIO_TO_ENCRYPTEDCONTENT),  "CMS_BIO_TO_ENCRYPTEDCONTENT"},
 {ERR_FUNC(CMS_F_CMS_COMPRESS), "CMS_compress"},
 {ERR_FUNC(CMS_F_CMS_COMPRESSEDDATA_CREATE),    "CMS_COMPRESSEDDATA_CREATE"},
 {ERR_FUNC(CMS_F_CMS_COMPRESSEDDATA_INIT_BIO),  "CMS_COMPRESSEDDATA_INIT_BIO"},
@@ -85,6 +86,7 @@ static ERR_STRING_DATA CMS_str_functs[]=
 {ERR_FUNC(CMS_F_CMS_DIGESTALGORITHM_INIT_BIO), "CMS_DIGESTALGORITHM_INIT_BIO"},
 {ERR_FUNC(CMS_F_CMS_DIGESTEDDATA_DO_FINAL),    "CMS_DIGESTEDDATA_DO_FINAL"},
 {ERR_FUNC(CMS_F_CMS_DIGEST_VERIFY),    "CMS_digest_verify"},
+{ERR_FUNC(CMS_F_CMS_ENCRYPTEDCONTENT_TO_BIO),  "CMS_ENCRYPTEDCONTENT_TO_BIO"},
 {ERR_FUNC(CMS_F_CMS_ENVELOPED_DATA_INIT),      "CMS_ENVELOPED_DATA_INIT"},
 {ERR_FUNC(CMS_F_CMS_FINAL),    "CMS_final"},
 {ERR_FUNC(CMS_F_CMS_GET0_CERTIFICATE_CHOICES), "CMS_GET0_CERTIFICATE_CHOICES"},
@@ -115,6 +117,8 @@ static ERR_STRING_DATA CMS_str_reasons[]=
        {
 {ERR_REASON(CMS_R_ADD_SIGNER_ERROR)      ,"add signer error"},
 {ERR_REASON(CMS_R_CERTIFICATE_VERIFY_ERROR),"certificate verify error"},
+{ERR_REASON(CMS_R_CIPHER_INITIALISATION_ERROR),"cipher initialisation error"},
+{ERR_REASON(CMS_R_CIPHER_PARAMETER_INITIALISATION_ERROR),"cipher parameter initialisation error"},
 {ERR_REASON(CMS_R_CMS_DATAFINAL_ERROR)   ,"cms datafinal error"},
 {ERR_REASON(CMS_R_CONTENT_NOT_FOUND)     ,"content not found"},
 {ERR_REASON(CMS_R_CONTENT_TYPE_NOT_COMPRESSED_DATA),"content type not compressed data"},
@@ -125,6 +129,7 @@ static ERR_STRING_DATA CMS_str_reasons[]=
 {ERR_REASON(CMS_R_CTRL_FAILURE)          ,"ctrl failure"},
 {ERR_REASON(CMS_R_ERROR_GETTING_PUBLIC_KEY),"error getting public key"},
 {ERR_REASON(CMS_R_ERROR_READING_MESSAGEDIGEST_ATTRIBUTE),"error reading messagedigest attribute"},
+{ERR_REASON(CMS_R_INVALID_KEY_LENGTH)    ,"invalid key length"},
 {ERR_REASON(CMS_R_MD_BIO_INIT_ERROR)     ,"md bio init error"},
 {ERR_REASON(CMS_R_MESSAGEDIGEST_ATTRIBUTE_WRONG_LENGTH),"messagedigest attribute wrong length"},
 {ERR_REASON(CMS_R_MESSAGEDIGEST_WRONG_LENGTH),"messagedigest wrong length"},
@@ -146,6 +151,7 @@ static ERR_STRING_DATA CMS_str_reasons[]=
 {ERR_REASON(CMS_R_TYPE_NOT_DATA)         ,"type not data"},
 {ERR_REASON(CMS_R_TYPE_NOT_DIGESTED_DATA),"type not digested data"},
 {ERR_REASON(CMS_R_UNABLE_TO_FINALIZE_CONTEXT),"unable to finalize context"},
+{ERR_REASON(CMS_R_UNKNOWN_CIPHER)        ,"unknown cipher"},
 {ERR_REASON(CMS_R_UNKNOWN_DIGEST_ALGORIHM),"unknown digest algorihm"},
 {ERR_REASON(CMS_R_UNKNOWN_ID)            ,"unknown id"},
 {ERR_REASON(CMS_R_UNSUPPORTED_COMPRESSION_ALGORITHM),"unsupported compression algorithm"},
index 1d77c88..1c7431b 100644 (file)
@@ -56,8 +56,8 @@
 my $badttest = 0;
 my $verbose = 1;
 
-my $cmscmd = "../apps/openssl cms";
-my $convcmd = "../apps/openssl x509 -inform DER";
+my $cmscmd = "../util/shlib_wrap.sh ../apps/openssl cms";
+my $convcmd = "../util/shlib_wrap.sh ../apps/openssl x509 -inform DER";
 my $exdir = "examples";
 
 my @test_list = (