Encrypted Data type processing. Add options to cms utility and run section 7
authorDr. Stephen Henson <steve@openssl.org>
Fri, 14 Mar 2008 13:21:48 +0000 (13:21 +0000)
committerDr. Stephen Henson <steve@openssl.org>
Fri, 14 Mar 2008 13:21:48 +0000 (13:21 +0000)
tests in RFC4134.

apps/cms.c
crypto/cms/cms.h
crypto/cms/cms_enc.c
crypto/cms/cms_err.c
crypto/cms/cms_lcl.h
crypto/cms/cms_lib.c
crypto/cms/cms_smime.c
test/runex.pl

index 9fd0aa0a86a21863b13f3ac0e1adbb37eaf46133..908e05acf055667b63b4d9450e435b34e4012281 100644 (file)
@@ -86,6 +86,7 @@ static int smime_cb(int ok, X509_STORE_CTX *ctx);
 #define SMIME_DIGEST_CREATE    (10 | SMIME_OP)
 #define SMIME_UNCOMPRESS       (11 | SMIME_IP)
 #define SMIME_COMPRESS         (12 | SMIME_OP)
+#define SMIME_ENCRYPTED_DECRYPT        (13 | SMIME_IP)
 
 int MAIN(int, char **);
 
@@ -121,6 +122,8 @@ int MAIN(int argc, char **argv)
 #ifndef OPENSSL_NO_ENGINE
        char *engine=NULL;
 #endif
+       unsigned char *secret_key = NULL;
+       size_t secret_keylen;
 
        X509_VERIFY_PARAM *vpm = NULL;
 
@@ -164,6 +167,8 @@ int MAIN(int argc, char **argv)
                        operation = SMIME_COMPRESS;
                else if (!strcmp (*args, "-uncompress"))
                        operation = SMIME_UNCOMPRESS;
+               else if (!strcmp (*args, "-EncrypedData_decrypt"))
+                       operation = SMIME_ENCRYPTED_DECRYPT;
 #ifndef OPENSSL_NO_DES
                else if (!strcmp (*args, "-des3")) 
                                cipher = EVP_des_ede3_cbc();
@@ -233,6 +238,20 @@ int MAIN(int argc, char **argv)
                                flags |= CMS_NOOLDMIMETYPE;
                else if (!strcmp (*args, "-crlfeol"))
                                flags |= CMS_CRLFEOL;
+               else if (!strcmp(*args,"-secretkey"))
+                       {
+                       long ltmp;
+                       if (!args[1])
+                               goto argerr;
+                       args++;
+                       secret_key = string_to_hex(*args, &ltmp);
+                       if (!secret_key)
+                               {
+                               BIO_printf(bio_err, "Invalid key %s\n", *args);
+                               goto argerr;
+                               }
+                       secret_keylen = (size_t)ltmp;
+                       }
                else if (!strcmp(*args,"-rand"))
                        {
                        if (!args[1])
@@ -810,6 +829,12 @@ int MAIN(int argc, char **argv)
                        goto end;
                        }
                }
+       else if (operation == SMIME_ENCRYPTED_DECRYPT)
+               {
+               if (!CMS_EncryptedData_decrypt(cms, secret_key, secret_keylen,
+                                               indata, out, flags))
+                       goto end;
+               }
        else if (operation == SMIME_VERIFY)
                {
                if (CMS_verify(cms, other, store, indata, out, flags) > 0)
@@ -878,6 +903,8 @@ end:
                sk_free(sksigners);
        if (skkeys)
                sk_free(skkeys);
+       if (secret_key)
+               OPENSSL_free(secret_key);
        X509_STORE_free(store);
        X509_free(cert);
        X509_free(recip);
index 0df4b0f4cff90d12c9089e80207cadfd740a358a..a95dda906e26516a42e4d19fb4e845b505dd9922 100644 (file)
@@ -138,6 +138,13 @@ int CMS_digest_verify(CMS_ContentInfo *cms, BIO *dcont, BIO *out,
 CMS_ContentInfo *CMS_digest_create(BIO *in, const EVP_MD *md,
                                                        unsigned int flags);
 
+int CMS_EncryptedData_decrypt(CMS_ContentInfo *cms,
+                               const unsigned char *key, size_t keylen,
+                               BIO *dcont, BIO *out, unsigned int flags);
+
+int CMS_EncryptedData_set1_key(BIO *b, CMS_ContentInfo *cms,
+                               const unsigned char *key, size_t keylen);
+
 int CMS_verify(CMS_ContentInfo *cms, STACK_OF(X509) *certs,
                 X509_STORE *store, BIO *dcont, BIO *out, unsigned int flags);
 
@@ -255,6 +262,8 @@ void ERR_load_CMS_strings(void);
 #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_ENCRYPTEDDATA_DECRYPT                         140
+#define CMS_F_CMS_ENCRYPTED_DATA_DECRYPT                139
 #define CMS_F_CMS_ENVELOPED_DATA_INIT                   114
 #define CMS_F_CMS_FINAL                                         115
 #define CMS_F_CMS_GET0_CERTIFICATE_CHOICES              116
@@ -315,6 +324,7 @@ void ERR_load_CMS_strings(void);
 #define CMS_R_TYPE_NOT_COMPRESSED_DATA                  128
 #define CMS_R_TYPE_NOT_DATA                             129
 #define CMS_R_TYPE_NOT_DIGESTED_DATA                    130
+#define CMS_R_TYPE_NOT_ENCRYPTED_DATA                   142
 #define CMS_R_UNABLE_TO_FINALIZE_CONTEXT                131
 #define CMS_R_UNKNOWN_CIPHER                            141
 #define CMS_R_UNKNOWN_DIGEST_ALGORIHM                   132
index 084bc124661a88a8329b4e4f2718bee7a8bf699e..b395bc499b7c2429f8c71662b25db205a988eea3 100644 (file)
@@ -132,18 +132,11 @@ int cms_bio_to_EncryptedContent(CMS_EncryptedContentInfo *ec,
 
 /* Return BIO based on EncryptedContentInfo and key */
 
-BIO *cms_EncryptedContent_to_bio(CMS_EncryptedContentInfo *ec,
+int cms_EncryptedContent_to_bio(BIO *b, 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);
@@ -187,10 +180,18 @@ BIO *cms_EncryptedContent_to_bio(CMS_EncryptedContentInfo *ec,
                                CMS_R_CIPHER_PARAMETER_INITIALISATION_ERROR);
                        goto err;
                        }
-       return b;
+       return 1;
 
        err:
-       BIO_free(b);
-       return NULL;
+       return 0;
        }
 
+int CMS_EncryptedData_set1_key(BIO *b, CMS_ContentInfo *cms,
+                               const unsigned char *key, size_t keylen)
+       {
+       CMS_EncryptedContentInfo *ec;
+       if (OBJ_obj2nid(cms->contentType) != NID_pkcs7_encrypted)
+               return 0;
+       ec = cms->d.encryptedData->encryptedContentInfo;
+       return cms_EncryptedContent_to_bio(b, ec, key, keylen);
+       }
index 8a45c059a8e3ef991b63912e04620f3e98f1e739..6fb6939b93f3c552a3fb8bc5a78ce51499324d62 100644 (file)
@@ -87,6 +87,8 @@ static ERR_STRING_DATA CMS_str_functs[]=
 {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_ENCRYPTEDDATA_DECRYPT),    "CMS_EncryptedData_decrypt"},
+{ERR_FUNC(CMS_F_CMS_ENCRYPTED_DATA_DECRYPT),   "CMS_ENCRYPTED_DATA_DECRYPT"},
 {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"},
@@ -150,6 +152,7 @@ static ERR_STRING_DATA CMS_str_reasons[]=
 {ERR_REASON(CMS_R_TYPE_NOT_COMPRESSED_DATA),"type not compressed data"},
 {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_TYPE_NOT_ENCRYPTED_DATA),"type not encrypted 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"},
index e33c274a105944b09bdc987672f40824218fc27e..cc22e00d531a77e104bc4ea25f96032320ebc48a 100644 (file)
@@ -411,6 +411,12 @@ void cms_DigestAlgorithm_set(X509_ALGOR *alg, const EVP_MD *md);
 BIO *cms_DigestAlgorithm_init_bio(X509_ALGOR *digestAlgorithm);
 int cms_DigestAlgorithm_find_ctx(EVP_MD_CTX *mctx, BIO *chain,
                                        X509_ALGOR *mdalg);
+
+int cms_bio_to_EncryptedContent(CMS_EncryptedContentInfo *ec,
+                                       const unsigned char *key, int keylen,
+                                       BIO *b);
+int cms_EncryptedContent_to_bio(BIO *b, CMS_EncryptedContentInfo *ec,
+                                       const unsigned char *key, int keylen);
        
 #ifdef  __cplusplus
 }
index 24ab0e7ba5ab9dc44574a7dffbf17c38ffa05939..f2169e138b3ca1ec657373d0676676162e63eff7 100644 (file)
@@ -139,6 +139,10 @@ BIO *CMS_dataInit(CMS_ContentInfo *cms, BIO *icont)
                break;
 #endif
 
+               case NID_pkcs7_encrypted:
+               cmsbio = BIO_new(BIO_f_cipher());
+               break;
+
                default:
                CMSerr(CMS_F_CMS_DATAINIT, CMS_R_UNSUPPORTED_TYPE);
                return NULL;
@@ -152,7 +156,7 @@ BIO *CMS_dataInit(CMS_ContentInfo *cms, BIO *icont)
        return NULL;
 
        }
-               
+
 int CMS_dataFinal(CMS_ContentInfo *cms, BIO *cmsbio)
        {
        ASN1_OCTET_STRING **pos = CMS_get0_content(cms);
index 0a67c786949675e668dd0119558be9f6f0672510..a1ee0f24e2ec7232ec8787f7948b61a27a107ba6 100644 (file)
@@ -188,6 +188,40 @@ CMS_ContentInfo *CMS_digest_create(BIO *in, const EVP_MD *md,
        return NULL;
        }
 
+int CMS_EncryptedData_decrypt(CMS_ContentInfo *cms,
+                               const unsigned char *key, size_t keylen,
+                               BIO *dcont, BIO *out, unsigned int flags)
+       {
+       BIO *cont;
+       int r;
+       if (OBJ_obj2nid(CMS_get0_type(cms)) != NID_pkcs7_encrypted)
+               {
+               CMSerr(CMS_F_CMS_ENCRYPTEDDATA_DECRYPT,
+                                       CMS_R_TYPE_NOT_ENCRYPTED_DATA);
+               return 0;
+               }
+
+       if (!dcont)
+               {
+               ASN1_OCTET_STRING **pos = CMS_get0_content(cms);
+               if (!pos || !*pos)
+                       {
+                       CMSerr(CMS_F_CMS_ENCRYPTEDDATA_DECRYPT,
+                                       CMS_R_NO_CONTENT);
+                       return 0;
+                       }
+               }
+
+       cont = CMS_dataInit(cms, dcont);
+       if (!cont)
+               return 0;
+       r = CMS_EncryptedData_set1_key(cont, cms, key, keylen);
+       if (r)
+               r = cms_copy_content(out, cont, flags);
+       BIO_free_all(cont);
+       return r;
+       }
+
 static int cms_signerinfo_verify_cert(CMS_SignerInfo *si,
                                        X509_STORE *store,
                                        STACK_OF(X509) *certs,
index 1c7431b8652aff722ff0199b1495474387443ee9..ff21f90702ece8f0f662d3d270fdee65f2b9e951 100644 (file)
@@ -77,10 +77,12 @@ my @test_list = (
 ["5.1.bin"     => "encode"],
 ["5.2.bin"     => "encode"],
 ["6.0.bin"     => "encode, digest, cont"],
-["7.1.bin"     => "encode"],
-["7.2.bin"     => "encode"]
+["7.1.bin"     => "encode, encrypted, cont"],
+["7.2.bin"     => "encode, encrypted, cont"]
 );
 
+my $secretkey = "73:7c:79:1f:25:ea:d0:e0:46:29:25:43:52:f7:dc:62:91:e5:cb:26:91:7a:da:32";
+
        if (!-d $exdir)
                {
                print STDERR "FATAL ERROR: examples directory missing!!\n";
@@ -111,6 +113,10 @@ foreach (@test_list) {
                {
                run_digest_test($exdir, $tlist, $file);
                }
+       if ($tlist =~ /encrypted/)
+               {
+               run_encrypted_test($exdir, $tlist, $file, $secretkey);
+               }
 
 }
 
@@ -234,6 +240,32 @@ sub run_digest_test
                }
        }
 
+sub run_encrypted_test
+       {
+       my ($cmsdir, $tlist, $tfile, $key) = @_;
+       unlink "tmp.txt";
+
+       system ("$cmscmd -EncrypedData_decrypt -inform DER" .
+               " -secretkey $key" .
+               " -in $cmsdir/$tfile -out tmp.txt");
+
+       if ($?)
+               {
+               print "\tEncrypted Data command FAILED!!\n";
+               $badtest++;
+               }
+       elsif ($tlist =~ /cont/ &&
+               !cmp_files("$cmsdir/ExContent.bin", "tmp.txt"))
+               {
+               print "\tEncrypted Data content compare FAILED!!\n";
+               $badtest++;
+               }
+       else
+               {
+               print "\tEncryptedData verify passed\n" if $verbose;
+               }
+       }
+
 sub cmp_files
        {
        my ($f1, $f2) = @_;