Import OpenSSL 0.9.8h.
authorPeter Avalos <pavalos@dragonflybsd.org>
Sat, 6 Sep 2008 20:36:16 +0000 (20:36 +0000)
committerPeter Avalos <pavalos@dragonflybsd.org>
Sat, 6 Sep 2008 20:36:16 +0000 (20:36 +0000)
129 files changed:
crypto/openssl-0.9/CHANGES
crypto/openssl-0.9/FAQ
crypto/openssl-0.9/LICENSE
crypto/openssl-0.9/README
crypto/openssl-0.9/apps/apps.c
crypto/openssl-0.9/apps/apps.h
crypto/openssl-0.9/apps/ca.c
crypto/openssl-0.9/apps/cms.c [new file with mode: 0644]
crypto/openssl-0.9/apps/dgst.c
crypto/openssl-0.9/apps/ec.c
crypto/openssl-0.9/apps/ocsp.c
crypto/openssl-0.9/apps/progs.h
crypto/openssl-0.9/apps/req.c
crypto/openssl-0.9/apps/rsautl.c
crypto/openssl-0.9/apps/s_client.c
crypto/openssl-0.9/apps/s_server.c
crypto/openssl-0.9/apps/speed.c
crypto/openssl-0.9/apps/x509.c
crypto/openssl-0.9/crypto/aes/aes.h
crypto/openssl-0.9/crypto/aes/aes_wrap.c [new file with mode: 0644]
crypto/openssl-0.9/crypto/asn1/a_object.c
crypto/openssl-0.9/crypto/asn1/a_type.c
crypto/openssl-0.9/crypto/asn1/asn1.h
crypto/openssl-0.9/crypto/asn1/asn1_err.c
crypto/openssl-0.9/crypto/asn1/asn1_lib.c
crypto/openssl-0.9/crypto/asn1/asn1t.h
crypto/openssl-0.9/crypto/asn1/asn_mime.c [copied from crypto/openssl-0.9/crypto/pkcs7/pk7_mime.c with 75% similarity]
crypto/openssl-0.9/crypto/asn1/t_x509.c
crypto/openssl-0.9/crypto/asn1/tasn_dec.c
crypto/openssl-0.9/crypto/asn1/tasn_enc.c
crypto/openssl-0.9/crypto/asn1/tasn_fre.c
crypto/openssl-0.9/crypto/asn1/x_algor.c
crypto/openssl-0.9/crypto/asn1/x_exten.c
crypto/openssl-0.9/crypto/bio/b_sock.c
crypto/openssl-0.9/crypto/bio/bio.h
crypto/openssl-0.9/crypto/bio/bss_dgram.c
crypto/openssl-0.9/crypto/bio/bss_file.c
crypto/openssl-0.9/crypto/bn/bn.h
crypto/openssl-0.9/crypto/bn/bn_lcl.h
crypto/openssl-0.9/crypto/bn/bn_mont.c
crypto/openssl-0.9/crypto/bn/bn_mul.c
crypto/openssl-0.9/crypto/bn/bn_nist.c
crypto/openssl-0.9/crypto/cms/Makefile [new file with mode: 0644]
crypto/openssl-0.9/crypto/cms/cms.h [new file with mode: 0644]
crypto/openssl-0.9/crypto/cms/cms_asn1.c [new file with mode: 0644]
crypto/openssl-0.9/crypto/cms/cms_att.c [new file with mode: 0644]
crypto/openssl-0.9/crypto/cms/cms_cd.c [copied from crypto/openssl-0.9/crypto/comp/comp_err.c with 56% similarity]
crypto/openssl-0.9/crypto/cms/cms_dd.c [copied from crypto/openssl-0.9/crypto/asn1/x_algor.c with 55% similarity]
crypto/openssl-0.9/crypto/cms/cms_enc.c [new file with mode: 0644]
crypto/openssl-0.9/crypto/cms/cms_env.c [new file with mode: 0644]
crypto/openssl-0.9/crypto/cms/cms_err.c [new file with mode: 0644]
crypto/openssl-0.9/crypto/cms/cms_ess.c [new file with mode: 0644]
crypto/openssl-0.9/crypto/cms/cms_io.c [copied from crypto/openssl-0.9/crypto/asn1/x_algor.c with 54% similarity]
crypto/openssl-0.9/crypto/cms/cms_lcl.h [new file with mode: 0644]
crypto/openssl-0.9/crypto/cms/cms_lib.c [new file with mode: 0644]
crypto/openssl-0.9/crypto/cms/cms_sd.c [new file with mode: 0644]
crypto/openssl-0.9/crypto/cms/cms_smime.c [new file with mode: 0644]
crypto/openssl-0.9/crypto/comp/c_zlib.c
crypto/openssl-0.9/crypto/comp/comp.h
crypto/openssl-0.9/crypto/comp/comp_err.c
crypto/openssl-0.9/crypto/des/des.h
crypto/openssl-0.9/crypto/des/des_old.c
crypto/openssl-0.9/crypto/des/des_old.h
crypto/openssl-0.9/crypto/des/xcbc_enc.c
crypto/openssl-0.9/crypto/ecdsa/ecs_ossl.c
crypto/openssl-0.9/crypto/engine/eng_padlock.c
crypto/openssl-0.9/crypto/engine/eng_table.c
crypto/openssl-0.9/crypto/err/err.c
crypto/openssl-0.9/crypto/err/err.h
crypto/openssl-0.9/crypto/err/err_all.c
crypto/openssl-0.9/crypto/md32_common.h
crypto/openssl-0.9/crypto/md4/md4_dgst.c
crypto/openssl-0.9/crypto/md4/md4_locl.h
crypto/openssl-0.9/crypto/md5/md5_dgst.c
crypto/openssl-0.9/crypto/md5/md5_locl.h
crypto/openssl-0.9/crypto/objects/obj_dat.c
crypto/openssl-0.9/crypto/objects/obj_dat.h
crypto/openssl-0.9/crypto/objects/obj_mac.h
crypto/openssl-0.9/crypto/ocsp/ocsp.h
crypto/openssl-0.9/crypto/ocsp/ocsp_err.c
crypto/openssl-0.9/crypto/ocsp/ocsp_ht.c
crypto/openssl-0.9/crypto/opensslv.h
crypto/openssl-0.9/crypto/ossl_typ.h
crypto/openssl-0.9/crypto/pem/pem.h
crypto/openssl-0.9/crypto/pem/pem_info.c
crypto/openssl-0.9/crypto/pkcs7/pk7_mime.c
crypto/openssl-0.9/crypto/rand/rand_nw.c
crypto/openssl-0.9/crypto/rand/randfile.c
crypto/openssl-0.9/crypto/rc4/rc4_skey.c
crypto/openssl-0.9/crypto/ripemd/rmd_dgst.c
crypto/openssl-0.9/crypto/ripemd/rmd_locl.h
crypto/openssl-0.9/crypto/rsa/rsa_eay.c
crypto/openssl-0.9/crypto/rsa/rsa_oaep.c
crypto/openssl-0.9/crypto/sha/sha256.c
crypto/openssl-0.9/crypto/sha/sha512.c
crypto/openssl-0.9/crypto/sha/sha_locl.h
crypto/openssl-0.9/crypto/stack/safestack.h
crypto/openssl-0.9/crypto/symhacks.h
crypto/openssl-0.9/crypto/x509/x509.h
crypto/openssl-0.9/crypto/x509/x509_att.c
crypto/openssl-0.9/crypto/x509v3/v3_utl.c
crypto/openssl-0.9/crypto/x509v3/x509v3.h
crypto/openssl-0.9/e_os.h
crypto/openssl-0.9/engines/e_4758cca_err.h
crypto/openssl-0.9/engines/e_aep.c
crypto/openssl-0.9/engines/e_aep_err.h
crypto/openssl-0.9/engines/e_atalla_err.h
crypto/openssl-0.9/engines/e_chil_err.h
crypto/openssl-0.9/engines/e_cswift_err.h
crypto/openssl-0.9/engines/e_gmp.c
crypto/openssl-0.9/engines/e_gmp_err.h
crypto/openssl-0.9/engines/e_nuron_err.h
crypto/openssl-0.9/engines/e_sureware_err.h
crypto/openssl-0.9/engines/e_ubsec_err.h
crypto/openssl-0.9/ssl/kssl.c
crypto/openssl-0.9/ssl/s23_clnt.c
crypto/openssl-0.9/ssl/s3_clnt.c
crypto/openssl-0.9/ssl/s3_lib.c
crypto/openssl-0.9/ssl/s3_srvr.c
crypto/openssl-0.9/ssl/ssl.h
crypto/openssl-0.9/ssl/ssl3.h
crypto/openssl-0.9/ssl/ssl_asn1.c
crypto/openssl-0.9/ssl/ssl_err.c
crypto/openssl-0.9/ssl/ssl_lib.c
crypto/openssl-0.9/ssl/ssl_locl.h
crypto/openssl-0.9/ssl/ssl_rsa.c
crypto/openssl-0.9/ssl/ssl_stat.c
crypto/openssl-0.9/ssl/t1_lib.c
crypto/openssl-0.9/ssl/tls1.h

index 512b115..217aa70 100644 (file)
@@ -2,6 +2,142 @@
  OpenSSL CHANGES
  _______________
 
+ Changes between 0.9.8g and 0.9.8h  [28 May 2008]
+
+  *) Fix flaw if 'Server Key exchange message' is omitted from a TLS
+     handshake which could lead to a cilent crash as found using the
+     Codenomicon TLS test suite (CVE-2008-1672) 
+     [Steve Henson, Mark Cox]
+
+  *) Fix double free in TLS server name extensions which could lead to
+     a remote crash found by Codenomicon TLS test suite (CVE-2008-0891) 
+     [Joe Orton]
+
+  *) Clear error queue in SSL_CTX_use_certificate_chain_file()
+
+     Clear the error queue to ensure that error entries left from
+     older function calls do not interfere with the correct operation.
+     [Lutz Jaenicke, Erik de Castro Lopo]
+
+  *) Remove root CA certificates of commercial CAs:
+
+     The OpenSSL project does not recommend any specific CA and does not
+     have any policy with respect to including or excluding any CA.
+     Therefore it does not make any sense to ship an arbitrary selection
+     of root CA certificates with the OpenSSL software.
+     [Lutz Jaenicke]
+
+  *) RSA OAEP patches to fix two separate invalid memory reads.
+     The first one involves inputs when 'lzero' is greater than
+     'SHA_DIGEST_LENGTH' (it would read about SHA_DIGEST_LENGTH bytes
+     before the beginning of from). The second one involves inputs where
+     the 'db' section contains nothing but zeroes (there is a one-byte
+     invalid read after the end of 'db').
+     [Ivan Nestlerode <inestlerode@us.ibm.com>]
+
+  *) Partial backport from 0.9.9-dev:
+
+     Introduce bn_mul_mont (dedicated Montgomery multiplication
+     procedure) as a candidate for BIGNUM assembler implementation.
+     While 0.9.9-dev uses assembler for various architectures, only
+     x86_64 is available by default here in the 0.9.8 branch, and
+     32-bit x86 is available through a compile-time setting.
+
+     To try the 32-bit x86 assembler implementation, use Configure
+     option "enable-montasm" (which exists only for this backport).
+
+     As "enable-montasm" for 32-bit x86 disclaims code stability
+     anyway, in this constellation we activate additional code
+     backported from 0.9.9-dev for further performance improvements,
+     namely BN_from_montgomery_word.  (To enable this otherwise,
+     e.g. x86_64, try "-DMONT_FROM_WORD___NON_DEFAULT_0_9_8_BUILD".)
+
+     [Andy Polyakov (backport partially by Bodo Moeller)]
+
+  *) Add TLS session ticket callback. This allows an application to set
+     TLS ticket cipher and HMAC keys rather than relying on hardcoded fixed
+     values. This is useful for key rollover for example where several key
+     sets may exist with different names.
+     [Steve Henson]
+
+  *) Reverse ENGINE-internal logic for caching default ENGINE handles.
+     This was broken until now in 0.9.8 releases, such that the only way
+     a registered ENGINE could be used (assuming it initialises
+     successfully on the host) was to explicitly set it as the default
+     for the relevant algorithms. This is in contradiction with 0.9.7
+     behaviour and the documentation. With this fix, when an ENGINE is
+     registered into a given algorithm's table of implementations, the
+     'uptodate' flag is reset so that auto-discovery will be used next
+     time a new context for that algorithm attempts to select an
+     implementation.
+     [Ian Lister (tweaked by Geoff Thorpe)]
+
+  *) Backport of CMS code to OpenSSL 0.9.8. This differs from the 0.9.9
+     implemention in the following ways:
+
+     Lack of EVP_PKEY_ASN1_METHOD means algorithm parameters have to be
+     hard coded.
+
+     Lack of BER streaming support means one pass streaming processing is
+     only supported if data is detached: setting the streaming flag is
+     ignored for embedded content.
+
+     CMS support is disabled by default and must be explicitly enabled
+     with the enable-cms configuration option.
+     [Steve Henson]
+
+  *) Update the GMP engine glue to do direct copies between BIGNUM and
+     mpz_t when openssl and GMP use the same limb size. Otherwise the
+     existing "conversion via a text string export" trick is still used.
+     [Paul Sheer <paulsheer@gmail.com>]
+
+  *) Zlib compression BIO. This is a filter BIO which compressed and
+     uncompresses any data passed through it.
+     [Steve Henson]
+
+  *) Add AES_wrap_key() and AES_unwrap_key() functions to implement
+     RFC3394 compatible AES key wrapping.
+     [Steve Henson]
+
+  *) Add utility functions to handle ASN1 structures. ASN1_STRING_set0():
+     sets string data without copying. X509_ALGOR_set0() and
+     X509_ALGOR_get0(): set and retrieve X509_ALGOR (AlgorithmIdentifier)
+     data. Attribute function X509at_get0_data_by_OBJ(): retrieves data
+     from an X509_ATTRIBUTE structure optionally checking it occurs only
+     once. ASN1_TYPE_set1(): set and ASN1_TYPE structure copying supplied
+     data.
+     [Steve Henson]
+
+  *) Fix BN flag handling in RSA_eay_mod_exp() and BN_MONT_CTX_set()
+     to get the expected BN_FLG_CONSTTIME behavior.
+     [Bodo Moeller (Google)]
+  
+  *) Netware support:
+
+     - fixed wrong usage of ioctlsocket() when build for LIBC BSD sockets
+     - fixed do_tests.pl to run the test suite with CLIB builds too (CLIB_OPT)
+     - added some more tests to do_tests.pl
+     - fixed RunningProcess usage so that it works with newer LIBC NDKs too
+     - removed usage of BN_LLONG for CLIB builds to avoid runtime dependency
+     - added new Configure targets netware-clib-bsdsock, netware-clib-gcc,
+       netware-clib-bsdsock-gcc, netware-libc-bsdsock-gcc
+     - various changes to netware.pl to enable gcc-cross builds on Win32
+       platform
+     - changed crypto/bio/b_sock.c to work with macro functions (CLIB BSD)
+     - various changes to fix missing prototype warnings
+     - fixed x86nasm.pl to create correct asm files for NASM COFF output
+     - added AES, WHIRLPOOL and CPUID assembler code to build files
+     - added missing AES assembler make rules to mk1mf.pl
+     - fixed order of includes in apps/ocsp.c so that e_os.h settings apply
+     [Guenter Knauf <eflash@gmx.net>]
+
+  *) Implement certificate status request TLS extension defined in RFC3546.
+     A client can set the appropriate parameters and receive the encoded
+     OCSP response via a callback. A server can query the supplied parameters
+     and set the encoded OCSP response in the callback. Add simplified examples
+     to s_client and s_server.
+     [Steve Henson]
+
  Changes between 0.9.8f and 0.9.8g  [19 Oct 2007]
 
   *) Fix various bugs:
      authentication-only ciphersuites.
      [Bodo Moeller]
 
+  *) Update the SSL_get_shared_ciphers() fix CVE-2006-3738 which was
+     not complete and could lead to a possible single byte overflow
+     (CVE-2007-5135) [Ben Laurie]
+
  Changes between 0.9.8d and 0.9.8e  [23 Feb 2007]
 
   *) Since AES128 and AES256 (and similarly Camellia128 and
index 96d39f5..09f700c 100644 (file)
@@ -32,6 +32,7 @@ OpenSSL  -  Frequently Asked Questions
 * How do I install a CA certificate into a browser?
 * Why is OpenSSL x509 DN output not conformant to RFC2253?
 * What is a "128 bit certificate"? Can I create one with OpenSSL?
+* How can I set up a bundle of commercial root CA certificates?
 
 [BUILD] Questions about building and testing OpenSSL
 
@@ -75,7 +76,7 @@ OpenSSL  -  Frequently Asked Questions
 * Which is the current version of OpenSSL?
 
 The current version is available from <URL: http://www.openssl.org>.
-OpenSSL 0.9.8g was released on October 19th, 2007.
+OpenSSL 0.9.8h was released on May 28th, 2008.
 
 In addition to the current stable release, you can also access daily
 snapshots of the OpenSSL development version at <URL:
@@ -426,6 +427,20 @@ The export laws were later changed to allow almost unrestricted use of strong
 encryption so these certificates are now obsolete.
 
 
+* How can I set up a bundle of commercial root CA certificates?
+
+The OpenSSL software is shipped without any root CA certificate as the
+OpenSSL project does not have any policy on including or excluding
+any specific CA and does not intend to set up such a policy. Deciding
+about which CAs to support is up to application developers or
+administrators.
+
+Other projects do have other policies so you can for example extract the CA
+bundle used by Mozilla and/or modssl as described in this article:
+
+  http://www.mail-archive.com/modssl-users@modssl.org/msg16980.html
+
+
 [BUILD] =======================================================================
 
 * Why does the linker complain about undefined symbols?
@@ -823,11 +838,11 @@ code itself (the hex digits after the second colon).
 
 * Why do I get errors about unknown algorithms?
 
-This can happen under several circumstances such as reading in an
-encrypted private key or attempting to decrypt a PKCS#12 file. The cause
-is forgetting to load OpenSSL's table of algorithms with
-OpenSSL_add_all_algorithms(). See the manual page for more information.
-
+The cause is forgetting to load OpenSSL's table of algorithms with
+OpenSSL_add_all_algorithms(). See the manual page for more information. This
+can cause several problems such as being unable to read in an encrypted
+PEM file, unable to decrypt a PKCS#12 file or signature failure when
+verifying certificates.
 
 * Why can't the OpenSSH configure script detect OpenSSL?
 
index ff99d97..a2c4adc 100644 (file)
@@ -12,7 +12,7 @@
   ---------------
 
 /* ====================================================================
- * Copyright (c) 1998-2007 The OpenSSL Project.  All rights reserved.
+ * Copyright (c) 1998-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
index 2b49835..df02ae0 100644 (file)
@@ -1,7 +1,7 @@
 
- OpenSSL 0.9.8g
+ OpenSSL 0.9.8h
 
- Copyright (c) 1998-2007 The OpenSSL Project
+ Copyright (c) 1998-2008 The OpenSSL Project
  Copyright (c) 1995-1998 Eric A. Young, Tim J. Hudson
  All rights reserved.
 
     - Stack Traceback (if the application dumps core)
 
  Report the bug to the OpenSSL project via the Request Tracker
- (http://www.openssl.org/support/rt2.html) by mail to:
+ (http://www.openssl.org/support/rt.html) by mail to:
 
     openssl-bugs@openssl.org
 
index 613c3ba..5209cab 100644 (file)
@@ -2010,7 +2010,7 @@ int parse_yesno(const char *str, int def)
                case 'y': /* yes */
                case 'Y': /* YES */
                case '1': /* 1 */
-                       ret = 0;
+                       ret = 1;
                        break;
                default:
                        ret = def;
index 26dcbc5..0df1708 100644 (file)
 #ifndef OPENSSL_NO_ENGINE
 #include <openssl/engine.h>
 #endif
+#ifndef OPENSSL_NO_OCSP
+#include <openssl/ocsp.h>
+#endif
 #include <openssl/ossl_typ.h>
 
 int app_RAND_load_file(const char *file, BIO *bio_e, int dont_warn);
@@ -228,6 +231,12 @@ extern BIO *bio_err;
 #  endif
 #endif
 
+#ifdef OPENSSL_SYSNAME_WIN32
+#  define openssl_fdset(a,b) FD_SET((unsigned int)a, b)
+#else
+#  define openssl_fdset(a,b) FD_SET(a, b)
+#endif
+
 typedef struct args_st
        {
        char **data;
@@ -275,6 +284,12 @@ X509_STORE *setup_verify(BIO *bp, char *CAfile, char *CApath);
 ENGINE *setup_engine(BIO *err, const char *engine, int debug);
 #endif
 
+#ifndef OPENSSL_NO_OCSP
+OCSP_RESPONSE *process_responder(BIO *err, OCSP_REQUEST *req,
+                       char *host, char *path, char *port, int use_ssl,
+                       int req_timeout);
+#endif
+
 int load_config(BIO *err, CONF *cnf);
 char *make_config_name(void);
 
index e9d79de..87f0405 100644 (file)
@@ -2882,13 +2882,22 @@ int old_entry_print(BIO *bp, ASN1_OBJECT *obj, ASN1_STRING *str)
        p=(char *)str->data;
        for (j=str->length; j>0; j--)
                {
+#ifdef CHARSET_EBCDIC
+               if ((*p >= 0x20) && (*p <= 0x7e))
+                       BIO_printf(bp,"%c",os_toebcdic[*p]);
+#else
                if ((*p >= ' ') && (*p <= '~'))
                        BIO_printf(bp,"%c",*p);
+#endif
                else if (*p & 0x80)
                        BIO_printf(bp,"\\0x%02X",*p);
                else if ((unsigned char)*p == 0xf7)
                        BIO_printf(bp,"^?");
+#ifdef CHARSET_EBCDIC
+               else    BIO_printf(bp,"^%c",os_toebcdic[*p+0x40]);
+#else
                else    BIO_printf(bp,"^%c",*p+'@');
+#endif
                p++;
                }
        BIO_printf(bp,"'\n");
diff --git a/crypto/openssl-0.9/apps/cms.c b/crypto/openssl-0.9/apps/cms.c
new file mode 100644 (file)
index 0000000..6d227ac
--- /dev/null
@@ -0,0 +1,1347 @@
+/* apps/cms.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.
+ * ====================================================================
+ */
+
+/* CMS utility function */
+
+#include <stdio.h>
+#include <string.h>
+#include "apps.h"
+
+#ifndef OPENSSL_NO_CMS
+
+#include <openssl/crypto.h>
+#include <openssl/pem.h>
+#include <openssl/err.h>
+#include <openssl/x509_vfy.h>
+#include <openssl/x509v3.h>
+#include <openssl/cms.h>
+
+#undef PROG
+#define PROG cms_main
+static int save_certs(char *signerfile, STACK_OF(X509) *signers);
+static int cms_cb(int ok, X509_STORE_CTX *ctx);
+static void receipt_request_print(BIO *out, CMS_ContentInfo *cms);
+static CMS_ReceiptRequest *make_receipt_request(STACK *rr_to, int rr_allorfirst,
+                                                               STACK *rr_from);
+
+#define SMIME_OP       0x10
+#define SMIME_IP       0x20
+#define SMIME_SIGNERS  0x40
+#define SMIME_ENCRYPT          (1 | SMIME_OP)
+#define SMIME_DECRYPT          (2 | SMIME_IP)
+#define SMIME_SIGN             (3 | SMIME_OP | SMIME_SIGNERS)
+#define SMIME_VERIFY           (4 | SMIME_IP)
+#define SMIME_CMSOUT           (5 | SMIME_IP | SMIME_OP)
+#define SMIME_RESIGN           (6 | SMIME_IP | SMIME_OP | SMIME_SIGNERS)
+#define SMIME_DATAOUT          (7 | SMIME_IP)
+#define SMIME_DATA_CREATE      (8 | SMIME_OP)
+#define SMIME_DIGEST_VERIFY    (9 | SMIME_IP)
+#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)
+#define SMIME_ENCRYPTED_ENCRYPT        (14 | SMIME_OP)
+#define SMIME_SIGN_RECEIPT     (15 | SMIME_IP | SMIME_OP)
+#define SMIME_VERIFY_RECEIPT   (16 | SMIME_IP)
+
+int MAIN(int, char **);
+
+int MAIN(int argc, char **argv)
+       {
+       ENGINE *e = NULL;
+       int operation = 0;
+       int ret = 0;
+       char **args;
+       const char *inmode = "r", *outmode = "w";
+       char *infile = NULL, *outfile = NULL, *rctfile = NULL;
+       char *signerfile = NULL, *recipfile = NULL;
+       STACK *sksigners = NULL, *skkeys = NULL;
+       char *certfile = NULL, *keyfile = NULL, *contfile=NULL;
+       char *certsoutfile = NULL;
+       const EVP_CIPHER *cipher = NULL;
+       CMS_ContentInfo *cms = NULL, *rcms = NULL;
+       X509_STORE *store = NULL;
+       X509 *cert = NULL, *recip = NULL, *signer = NULL;
+       EVP_PKEY *key = NULL;
+       STACK_OF(X509) *encerts = NULL, *other = NULL;
+       BIO *in = NULL, *out = NULL, *indata = NULL, *rctin = NULL;
+       int badarg = 0;
+       int flags = CMS_DETACHED;
+       int rr_print = 0, rr_allorfirst = -1;
+       STACK *rr_to = NULL, *rr_from = NULL;
+       CMS_ReceiptRequest *rr = NULL;
+       char *to = NULL, *from = NULL, *subject = NULL;
+       char *CAfile = NULL, *CApath = NULL;
+       char *passargin = NULL, *passin = NULL;
+       char *inrand = NULL;
+       int need_rand = 0;
+       const EVP_MD *sign_md = NULL;
+       int informat = FORMAT_SMIME, outformat = FORMAT_SMIME;
+        int rctformat = FORMAT_SMIME, keyform = FORMAT_PEM;
+#ifndef OPENSSL_NO_ENGINE
+       char *engine=NULL;
+#endif
+       unsigned char *secret_key = NULL, *secret_keyid = NULL;
+       size_t secret_keylen = 0, secret_keyidlen = 0;
+
+       ASN1_OBJECT *econtent_type = NULL;
+
+       X509_VERIFY_PARAM *vpm = NULL;
+
+       args = argv + 1;
+       ret = 1;
+
+       apps_startup();
+
+       if (bio_err == NULL)
+               {
+               if ((bio_err = BIO_new(BIO_s_file())) != NULL)
+                       BIO_set_fp(bio_err, stderr, BIO_NOCLOSE|BIO_FP_TEXT);
+               }
+
+       if (!load_config(bio_err, NULL))
+               goto end;
+
+       while (!badarg && *args && *args[0] == '-')
+               {
+               if (!strcmp (*args, "-encrypt"))
+                       operation = SMIME_ENCRYPT;
+               else if (!strcmp (*args, "-decrypt"))
+                       operation = SMIME_DECRYPT;
+               else if (!strcmp (*args, "-sign"))
+                       operation = SMIME_SIGN;
+               else if (!strcmp (*args, "-sign_receipt"))
+                       operation = SMIME_SIGN_RECEIPT;
+               else if (!strcmp (*args, "-resign"))
+                       operation = SMIME_RESIGN;
+               else if (!strcmp (*args, "-verify"))
+                       operation = SMIME_VERIFY;
+               else if (!strcmp(*args,"-verify_receipt"))
+                       {
+                       operation = SMIME_VERIFY_RECEIPT;
+                       if (!args[1])
+                               goto argerr;
+                       args++;
+                       rctfile = *args;
+                       }
+               else if (!strcmp (*args, "-cmsout"))
+                       operation = SMIME_CMSOUT;
+               else if (!strcmp (*args, "-data_out"))
+                       operation = SMIME_DATAOUT;
+               else if (!strcmp (*args, "-data_create"))
+                       operation = SMIME_DATA_CREATE;
+               else if (!strcmp (*args, "-digest_verify"))
+                       operation = SMIME_DIGEST_VERIFY;
+               else if (!strcmp (*args, "-digest_create"))
+                       operation = SMIME_DIGEST_CREATE;
+               else if (!strcmp (*args, "-compress"))
+                       operation = SMIME_COMPRESS;
+               else if (!strcmp (*args, "-uncompress"))
+                       operation = SMIME_UNCOMPRESS;
+               else if (!strcmp (*args, "-EncryptedData_decrypt"))
+                       operation = SMIME_ENCRYPTED_DECRYPT;
+               else if (!strcmp (*args, "-EncryptedData_encrypt"))
+                       operation = SMIME_ENCRYPTED_ENCRYPT;
+#ifndef OPENSSL_NO_DES
+               else if (!strcmp (*args, "-des3")) 
+                               cipher = EVP_des_ede3_cbc();
+               else if (!strcmp (*args, "-des")) 
+                               cipher = EVP_des_cbc();
+#endif
+#ifndef OPENSSL_NO_SEED
+               else if (!strcmp (*args, "-seed")) 
+                               cipher = EVP_seed_cbc();
+#endif
+#ifndef OPENSSL_NO_RC2
+               else if (!strcmp (*args, "-rc2-40")) 
+                               cipher = EVP_rc2_40_cbc();
+               else if (!strcmp (*args, "-rc2-128")) 
+                               cipher = EVP_rc2_cbc();
+               else if (!strcmp (*args, "-rc2-64")) 
+                               cipher = EVP_rc2_64_cbc();
+#endif
+#ifndef OPENSSL_NO_AES
+               else if (!strcmp(*args,"-aes128"))
+                               cipher = EVP_aes_128_cbc();
+               else if (!strcmp(*args,"-aes192"))
+                               cipher = EVP_aes_192_cbc();
+               else if (!strcmp(*args,"-aes256"))
+                               cipher = EVP_aes_256_cbc();
+#endif
+#ifndef OPENSSL_NO_CAMELLIA
+               else if (!strcmp(*args,"-camellia128"))
+                               cipher = EVP_camellia_128_cbc();
+               else if (!strcmp(*args,"-camellia192"))
+                               cipher = EVP_camellia_192_cbc();
+               else if (!strcmp(*args,"-camellia256"))
+                               cipher = EVP_camellia_256_cbc();
+#endif
+               else if (!strcmp (*args, "-text")) 
+                               flags |= CMS_TEXT;
+               else if (!strcmp (*args, "-nointern")) 
+                               flags |= CMS_NOINTERN;
+               else if (!strcmp (*args, "-noverify") 
+                       || !strcmp (*args, "-no_signer_cert_verify")) 
+                               flags |= CMS_NO_SIGNER_CERT_VERIFY;
+               else if (!strcmp (*args, "-nocerts")) 
+                               flags |= CMS_NOCERTS;
+               else if (!strcmp (*args, "-noattr")) 
+                               flags |= CMS_NOATTR;
+               else if (!strcmp (*args, "-nodetach")) 
+                               flags &= ~CMS_DETACHED;
+               else if (!strcmp (*args, "-nosmimecap"))
+                               flags |= CMS_NOSMIMECAP;
+               else if (!strcmp (*args, "-binary"))
+                               flags |= CMS_BINARY;
+               else if (!strcmp (*args, "-keyid"))
+                               flags |= CMS_USE_KEYID;
+               else if (!strcmp (*args, "-nosigs"))
+                               flags |= CMS_NOSIGS;
+               else if (!strcmp (*args, "-no_content_verify"))
+                               flags |= CMS_NO_CONTENT_VERIFY;
+               else if (!strcmp (*args, "-no_attr_verify"))
+                               flags |= CMS_NO_ATTR_VERIFY;
+               else if (!strcmp (*args, "-stream"))
+                               {
+                               args++;
+                               continue;
+                               }
+               else if (!strcmp (*args, "-indef"))
+                               {
+                               args++;
+                               continue;
+                               }
+               else if (!strcmp (*args, "-noindef"))
+                               flags &= ~CMS_STREAM;
+               else if (!strcmp (*args, "-nooldmime"))
+                               flags |= CMS_NOOLDMIMETYPE;
+               else if (!strcmp (*args, "-crlfeol"))
+                               flags |= CMS_CRLFEOL;
+               else if (!strcmp (*args, "-receipt_request_print"))
+                               rr_print = 1;
+               else if (!strcmp (*args, "-receipt_request_all"))
+                               rr_allorfirst = 0;
+               else if (!strcmp (*args, "-receipt_request_first"))
+                               rr_allorfirst = 1;
+               else if (!strcmp(*args,"-receipt_request_from"))
+                       {
+                       if (!args[1])
+                               goto argerr;
+                       args++;
+                       if (!rr_from)
+                               rr_from = sk_new_null();
+                       sk_push(rr_from, *args);
+                       }
+               else if (!strcmp(*args,"-receipt_request_to"))
+                       {
+                       if (!args[1])
+                               goto argerr;
+                       args++;
+                       if (!rr_to)
+                               rr_to = sk_new_null();
+                       sk_push(rr_to, *args);
+                       }
+               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,"-secretkeyid"))
+                       {
+                       long ltmp;
+                       if (!args[1])
+                               goto argerr;
+                       args++;
+                       secret_keyid = string_to_hex(*args, &ltmp);
+                       if (!secret_keyid)
+                               {
+                               BIO_printf(bio_err, "Invalid id %s\n", *args);
+                               goto argerr;
+                               }
+                       secret_keyidlen = (size_t)ltmp;
+                       }
+               else if (!strcmp(*args,"-econtent_type"))
+                       {
+                       if (!args[1])
+                               goto argerr;
+                       args++;
+                       econtent_type = OBJ_txt2obj(*args, 0);
+                       if (!econtent_type)
+                               {
+                               BIO_printf(bio_err, "Invalid OID %s\n", *args);
+                               goto argerr;
+                               }
+                       }
+               else if (!strcmp(*args,"-rand"))
+                       {
+                       if (!args[1])
+                               goto argerr;
+                       args++;
+                       inrand = *args;
+                       need_rand = 1;
+                       }
+#ifndef OPENSSL_NO_ENGINE
+               else if (!strcmp(*args,"-engine"))
+                       {
+                       if (!args[1])
+                               goto argerr;
+                       engine = *++args;
+                       }
+#endif
+               else if (!strcmp(*args,"-passin"))
+                       {
+                       if (!args[1])
+                               goto argerr;
+                       passargin = *++args;
+                       }
+               else if (!strcmp (*args, "-to"))
+                       {
+                       if (!args[1])
+                               goto argerr;
+                       to = *++args;
+                       }
+               else if (!strcmp (*args, "-from"))
+                       {
+                       if (!args[1])
+                               goto argerr;
+                       from = *++args;
+                       }
+               else if (!strcmp (*args, "-subject"))
+                       {
+                       if (!args[1])
+                               goto argerr;
+                       subject = *++args;
+                       }
+               else if (!strcmp (*args, "-signer"))
+                       {
+                       if (!args[1])
+                               goto argerr;
+                       /* If previous -signer argument add signer to list */
+
+                       if (signerfile)
+                               {
+                               if (!sksigners)
+                                       sksigners = sk_new_null();
+                               sk_push(sksigners, signerfile);
+                               if (!keyfile)
+                                       keyfile = signerfile;
+                               if (!skkeys)
+                                       skkeys = sk_new_null();
+                               sk_push(skkeys, keyfile);
+                               keyfile = NULL;
+                               }
+                       signerfile = *++args;
+                       }
+               else if (!strcmp (*args, "-recip"))
+                       {
+                       if (!args[1])
+                               goto argerr;
+                       recipfile = *++args;
+                       }
+               else if (!strcmp (*args, "-certsout"))
+                       {
+                       if (!args[1])
+                               goto argerr;
+                       certsoutfile = *++args;
+                       }
+               else if (!strcmp (*args, "-md"))
+                       {
+                       if (!args[1])
+                               goto argerr;
+                       sign_md = EVP_get_digestbyname(*++args);
+                       if (sign_md == NULL)
+                               {
+                               BIO_printf(bio_err, "Unknown digest %s\n",
+                                                       *args);
+                               goto argerr;
+                               }
+                       }
+               else if (!strcmp (*args, "-inkey"))
+                       {
+                       if (!args[1])   
+                               goto argerr;
+                       /* If previous -inkey arument add signer to list */
+                       if (keyfile)
+                               {
+                               if (!signerfile)
+                                       {
+                                       BIO_puts(bio_err, "Illegal -inkey without -signer\n");
+                                       goto argerr;
+                                       }
+                               if (!sksigners)
+                                       sksigners = sk_new_null();
+                               sk_push(sksigners, signerfile);
+                               signerfile = NULL;
+                               if (!skkeys)
+                                       skkeys = sk_new_null();
+                               sk_push(skkeys, keyfile);
+                               }
+                       keyfile = *++args;
+                       }
+               else if (!strcmp (*args, "-keyform"))
+                       {
+                       if (!args[1])
+                               goto argerr;
+                       keyform = str2fmt(*++args);
+                       }
+               else if (!strcmp (*args, "-rctform"))
+                       {
+                       if (!args[1])
+                               goto argerr;
+                       rctformat = str2fmt(*++args);
+                       }
+               else if (!strcmp (*args, "-certfile"))
+                       {
+                       if (!args[1])
+                               goto argerr;
+                       certfile = *++args;
+                       }
+               else if (!strcmp (*args, "-CAfile"))
+                       {
+                       if (!args[1])
+                               goto argerr;
+                       CAfile = *++args;
+                       }
+               else if (!strcmp (*args, "-CApath"))
+                       {
+                       if (!args[1])
+                               goto argerr;
+                       CApath = *++args;
+                       }
+               else if (!strcmp (*args, "-in"))
+                       {
+                       if (!args[1])
+                               goto argerr;
+                       infile = *++args;
+                       }
+               else if (!strcmp (*args, "-inform"))
+                       {
+                       if (!args[1])
+                               goto argerr;
+                       informat = str2fmt(*++args);
+                       }
+               else if (!strcmp (*args, "-outform"))
+                       {
+                       if (!args[1])
+                               goto argerr;
+                       outformat = str2fmt(*++args);
+                       }
+               else if (!strcmp (*args, "-out"))
+                       {
+                       if (!args[1])
+                               goto argerr;
+                       outfile = *++args;
+                       }
+               else if (!strcmp (*args, "-content"))
+                       {
+                       if (!args[1])
+                               goto argerr;
+                       contfile = *++args;
+                       }
+               else if (args_verify(&args, NULL, &badarg, bio_err, &vpm))
+                       continue;
+               else if ((cipher = EVP_get_cipherbyname(*args + 1)) == NULL)
+                       badarg = 1;
+               args++;
+               }
+
+       if (((rr_allorfirst != -1) || rr_from) && !rr_to)
+               {
+               BIO_puts(bio_err, "No Signed Receipts Recipients\n");
+               goto argerr;
+               }
+
+       if (!(operation & SMIME_SIGNERS)  && (rr_to || rr_from))
+               {
+               BIO_puts(bio_err, "Signed receipts only allowed with -sign\n");
+               goto argerr;
+               }
+       if (!(operation & SMIME_SIGNERS) && (skkeys || sksigners))
+               {
+               BIO_puts(bio_err, "Multiple signers or keys not allowed\n");
+               goto argerr;
+               }
+
+       if (operation & SMIME_SIGNERS)
+               {
+               if (keyfile && !signerfile)
+                       {
+                       BIO_puts(bio_err, "Illegal -inkey without -signer\n");
+                       goto argerr;
+                       }
+               /* Check to see if any final signer needs to be appended */
+               if (signerfile)
+                       {
+                       if (!sksigners)
+                               sksigners = sk_new_null();
+                       sk_push(sksigners, signerfile);
+                       if (!skkeys)
+                               skkeys = sk_new_null();
+                       if (!keyfile)
+                               keyfile = signerfile;
+                       sk_push(skkeys, keyfile);
+                       }
+               if (!sksigners)
+                       {
+                       BIO_printf(bio_err, "No signer certificate specified\n");
+                       badarg = 1;
+                       }
+               signerfile = NULL;
+               keyfile = NULL;
+               need_rand = 1;
+               }
+
+       else if (operation == SMIME_DECRYPT)
+               {
+               if (!recipfile && !keyfile && !secret_key)
+                       {
+                       BIO_printf(bio_err, "No recipient certificate or key specified\n");
+                       badarg = 1;
+                       }
+               }
+       else if (operation == SMIME_ENCRYPT)
+               {
+               if (!*args && !secret_key)
+                       {
+                       BIO_printf(bio_err, "No recipient(s) certificate(s) specified\n");
+                       badarg = 1;
+                       }
+               need_rand = 1;
+               }
+       else if (!operation)
+               badarg = 1;
+
+       if (badarg)
+               {
+               argerr:
+               BIO_printf (bio_err, "Usage cms [options] cert.pem ...\n");
+               BIO_printf (bio_err, "where options are\n");
+               BIO_printf (bio_err, "-encrypt       encrypt message\n");
+               BIO_printf (bio_err, "-decrypt       decrypt encrypted message\n");
+               BIO_printf (bio_err, "-sign          sign message\n");
+               BIO_printf (bio_err, "-verify        verify signed message\n");
+               BIO_printf (bio_err, "-cmsout        output CMS structure\n");
+#ifndef OPENSSL_NO_DES
+               BIO_printf (bio_err, "-des3          encrypt with triple DES\n");
+               BIO_printf (bio_err, "-des           encrypt with DES\n");
+#endif
+#ifndef OPENSSL_NO_SEED
+               BIO_printf (bio_err, "-seed          encrypt with SEED\n");
+#endif
+#ifndef OPENSSL_NO_RC2
+               BIO_printf (bio_err, "-rc2-40        encrypt with RC2-40 (default)\n");
+               BIO_printf (bio_err, "-rc2-64        encrypt with RC2-64\n");
+               BIO_printf (bio_err, "-rc2-128       encrypt with RC2-128\n");
+#endif
+#ifndef OPENSSL_NO_AES
+               BIO_printf (bio_err, "-aes128, -aes192, -aes256\n");
+               BIO_printf (bio_err, "               encrypt PEM output with cbc aes\n");
+#endif
+#ifndef OPENSSL_NO_CAMELLIA
+               BIO_printf (bio_err, "-camellia128, -camellia192, -camellia256\n");
+               BIO_printf (bio_err, "               encrypt PEM output with cbc camellia\n");
+#endif
+               BIO_printf (bio_err, "-nointern      don't search certificates in message for signer\n");
+               BIO_printf (bio_err, "-nosigs        don't verify message signature\n");
+               BIO_printf (bio_err, "-noverify      don't verify signers certificate\n");
+               BIO_printf (bio_err, "-nocerts       don't include signers certificate when signing\n");
+               BIO_printf (bio_err, "-nodetach      use opaque signing\n");
+               BIO_printf (bio_err, "-noattr        don't include any signed attributes\n");
+               BIO_printf (bio_err, "-binary        don't translate message to text\n");
+               BIO_printf (bio_err, "-certfile file other certificates file\n");
+               BIO_printf (bio_err, "-certsout file certificate output file\n");
+               BIO_printf (bio_err, "-signer file   signer certificate file\n");
+               BIO_printf (bio_err, "-recip  file   recipient certificate file for decryption\n");
+               BIO_printf (bio_err, "-skeyid        use subject key identifier\n");
+               BIO_printf (bio_err, "-in file       input file\n");
+               BIO_printf (bio_err, "-inform arg    input format SMIME (default), PEM or DER\n");
+               BIO_printf (bio_err, "-inkey file    input private key (if not signer or recipient)\n");
+               BIO_printf (bio_err, "-keyform arg   input private key format (PEM or ENGINE)\n");
+               BIO_printf (bio_err, "-out file      output file\n");
+               BIO_printf (bio_err, "-outform arg   output format SMIME (default), PEM or DER\n");
+               BIO_printf (bio_err, "-content file  supply or override content for detached signature\n");
+               BIO_printf (bio_err, "-to addr       to address\n");
+               BIO_printf (bio_err, "-from ad       from address\n");
+               BIO_printf (bio_err, "-subject s     subject\n");
+               BIO_printf (bio_err, "-text          include or delete text MIME headers\n");
+               BIO_printf (bio_err, "-CApath dir    trusted certificates directory\n");
+               BIO_printf (bio_err, "-CAfile file   trusted certificates file\n");
+               BIO_printf (bio_err, "-crl_check     check revocation status of signer's certificate using CRLs\n");
+               BIO_printf (bio_err, "-crl_check_all check revocation status of signer's certificate chain using CRLs\n");
+#ifndef OPENSSL_NO_ENGINE
+               BIO_printf (bio_err, "-engine e      use engine e, possibly a hardware device.\n");
+#endif
+               BIO_printf (bio_err, "-passin arg    input file pass phrase source\n");
+               BIO_printf(bio_err,  "-rand file%cfile%c...\n", LIST_SEPARATOR_CHAR, LIST_SEPARATOR_CHAR);
+               BIO_printf(bio_err,  "               load the file (or the files in the directory) into\n");
+               BIO_printf(bio_err,  "               the random number generator\n");
+               BIO_printf (bio_err, "cert.pem       recipient certificate(s) for encryption\n");
+               goto end;
+               }
+
+#ifndef OPENSSL_NO_ENGINE
+        e = setup_engine(bio_err, engine, 0);
+#endif
+
+       if (!app_passwd(bio_err, passargin, NULL, &passin, NULL))
+               {
+               BIO_printf(bio_err, "Error getting password\n");
+               goto end;
+               }
+
+       if (need_rand)
+               {
+               app_RAND_load_file(NULL, bio_err, (inrand != NULL));
+               if (inrand != NULL)
+                       BIO_printf(bio_err,"%ld semi-random bytes loaded\n",
+                               app_RAND_load_files(inrand));
+               }
+
+       ret = 2;
+
+       if (!(operation & SMIME_SIGNERS))
+               flags &= ~CMS_DETACHED;
+
+       if (operation & SMIME_OP)
+               {
+               if (outformat == FORMAT_ASN1)
+                       outmode = "wb";
+               }
+       else
+               {
+               if (flags & CMS_BINARY)
+                       outmode = "wb";
+               }
+
+       if (operation & SMIME_IP)
+               {
+               if (informat == FORMAT_ASN1)
+                       inmode = "rb";
+               }
+       else
+               {
+               if (flags & CMS_BINARY)
+                       inmode = "rb";
+               }
+
+       if (operation == SMIME_ENCRYPT)
+               {
+               if (!cipher)
+                       {
+#ifndef OPENSSL_NO_DES                 
+                       cipher = EVP_des_ede3_cbc();
+#else
+                       BIO_printf(bio_err, "No cipher selected\n");
+                       goto end;
+#endif
+                       }
+
+               if (secret_key && !secret_keyid)
+                       {
+                       BIO_printf(bio_err, "No sectre key id\n");
+                       goto end;
+                       }
+
+               if (*args)
+                       encerts = sk_X509_new_null();
+               while (*args)
+                       {
+                       if (!(cert = load_cert(bio_err,*args,FORMAT_PEM,
+                               NULL, e, "recipient certificate file")))
+                               goto end;
+                       sk_X509_push(encerts, cert);
+                       cert = NULL;
+                       args++;
+                       }
+               }
+
+       if (certfile)
+               {
+               if (!(other = load_certs(bio_err,certfile,FORMAT_PEM, NULL,
+                       e, "certificate file")))
+                       {
+                       ERR_print_errors(bio_err);
+                       goto end;
+                       }
+               }
+
+       if (recipfile && (operation == SMIME_DECRYPT))
+               {
+               if (!(recip = load_cert(bio_err,recipfile,FORMAT_PEM,NULL,
+                       e, "recipient certificate file")))
+                       {
+                       ERR_print_errors(bio_err);
+                       goto end;
+                       }
+               }
+
+       if (operation == SMIME_SIGN_RECEIPT)
+               {
+               if (!(signer = load_cert(bio_err,signerfile,FORMAT_PEM,NULL,
+                       e, "receipt signer certificate file")))
+                       {
+                       ERR_print_errors(bio_err);
+                       goto end;
+                       }
+               }
+
+       if (operation == SMIME_DECRYPT)
+               {
+               if (!keyfile)
+                       keyfile = recipfile;
+               }
+       else if ((operation == SMIME_SIGN) || (operation == SMIME_SIGN_RECEIPT))
+               {
+               if (!keyfile)
+                       keyfile = signerfile;
+               }
+       else keyfile = NULL;
+
+       if (keyfile)
+               {
+               key = load_key(bio_err, keyfile, keyform, 0, passin, e,
+                              "signing key file");
+               if (!key)
+                       goto end;
+               }
+
+       if (infile)
+               {
+               if (!(in = BIO_new_file(infile, inmode)))
+                       {
+                       BIO_printf (bio_err,
+                                "Can't open input file %s\n", infile);
+                       goto end;
+                       }
+               }
+       else
+               in = BIO_new_fp(stdin, BIO_NOCLOSE);
+
+       if (operation & SMIME_IP)
+               {
+               if (informat == FORMAT_SMIME) 
+                       cms = SMIME_read_CMS(in, &indata);
+               else if (informat == FORMAT_PEM) 
+                       cms = PEM_read_bio_CMS(in, NULL, NULL, NULL);
+               else if (informat == FORMAT_ASN1) 
+                       cms = d2i_CMS_bio(in, NULL);
+               else
+                       {
+                       BIO_printf(bio_err, "Bad input format for CMS file\n");
+                       goto end;
+                       }
+
+               if (!cms)
+                       {
+                       BIO_printf(bio_err, "Error reading S/MIME message\n");
+                       goto end;
+                       }
+               if (contfile)
+                       {
+                       BIO_free(indata);
+                       if (!(indata = BIO_new_file(contfile, "rb")))
+                               {
+                               BIO_printf(bio_err, "Can't read content file %s\n", contfile);
+                               goto end;
+                               }
+                       }
+               if (certsoutfile)
+                       {
+                       STACK_OF(X509) *allcerts;
+                       allcerts = CMS_get1_certs(cms);
+                       if (!save_certs(certsoutfile, allcerts))
+                               {
+                               BIO_printf(bio_err,
+                                               "Error writing certs to %s\n",
+                                                               certsoutfile);
+                               ret = 5;
+                               goto end;
+                               }
+                       sk_X509_pop_free(allcerts, X509_free);
+                       }
+               }
+
+       if (rctfile)
+               {
+               char *rctmode = (rctformat == FORMAT_ASN1) ? "rb" : "r";
+               if (!(rctin = BIO_new_file(rctfile, rctmode)))
+                       {
+                       BIO_printf (bio_err,
+                                "Can't open receipt file %s\n", rctfile);
+                       goto end;
+                       }
+               
+               if (rctformat == FORMAT_SMIME) 
+                       rcms = SMIME_read_CMS(rctin, NULL);
+               else if (rctformat == FORMAT_PEM) 
+                       rcms = PEM_read_bio_CMS(rctin, NULL, NULL, NULL);
+               else if (rctformat == FORMAT_ASN1) 
+                       rcms = d2i_CMS_bio(rctin, NULL);
+               else
+                       {
+                       BIO_printf(bio_err, "Bad input format for receipt\n");
+                       goto end;
+                       }
+
+               if (!rcms)
+                       {
+                       BIO_printf(bio_err, "Error reading receipt\n");
+                       goto end;
+                       }
+               }
+
+       if (outfile)
+               {
+               if (!(out = BIO_new_file(outfile, outmode)))
+                       {
+                       BIO_printf (bio_err,
+                                "Can't open output file %s\n", outfile);
+                       goto end;
+                       }
+               }
+       else
+               {
+               out = BIO_new_fp(stdout, BIO_NOCLOSE);
+#ifdef OPENSSL_SYS_VMS
+               {
+                   BIO *tmpbio = BIO_new(BIO_f_linebuffer());
+                   out = BIO_push(tmpbio, out);
+               }
+#endif
+               }
+
+       if ((operation == SMIME_VERIFY) || (operation == SMIME_VERIFY_RECEIPT))
+               {
+               if (!(store = setup_verify(bio_err, CAfile, CApath)))
+                       goto end;
+               X509_STORE_set_verify_cb_func(store, cms_cb);
+               if (vpm)
+                       X509_STORE_set1_param(store, vpm);
+               }
+
+
+       ret = 3;
+
+       if (operation == SMIME_DATA_CREATE)
+               {
+               cms = CMS_data_create(in, flags);
+               }
+       else if (operation == SMIME_DIGEST_CREATE)
+               {
+               cms = CMS_digest_create(in, sign_md, flags);
+               }
+       else if (operation == SMIME_COMPRESS)
+               {
+               cms = CMS_compress(in, -1, flags);
+               }
+       else if (operation == SMIME_ENCRYPT)
+               {
+               flags |= CMS_PARTIAL;
+               cms = CMS_encrypt(encerts, in, cipher, flags);
+               if (!cms)
+                       goto end;
+               if (secret_key)
+                       {
+                       if (!CMS_add0_recipient_key(cms, NID_undef, 
+                                               secret_key, secret_keylen,
+                                               secret_keyid, secret_keyidlen,
+                                               NULL, NULL, NULL))
+                               goto end;
+                       /* NULL these because call absorbs them */
+                       secret_key = NULL;
+                       secret_keyid = NULL;
+                       }
+               if (!(flags & CMS_STREAM))
+                       {
+                       if (!CMS_final(cms, in, NULL, flags))
+                               goto end;
+                       }
+               }
+       else if (operation == SMIME_ENCRYPTED_ENCRYPT)
+               {
+               cms = CMS_EncryptedData_encrypt(in, cipher,
+                                               secret_key, secret_keylen,
+                                               flags);
+
+               }
+       else if (operation == SMIME_SIGN_RECEIPT)
+               {
+               CMS_ContentInfo *srcms = NULL;
+               STACK_OF(CMS_SignerInfo) *sis;
+               CMS_SignerInfo *si;
+               sis = CMS_get0_SignerInfos(cms);
+               if (!sis)
+                       goto end;
+               si = sk_CMS_SignerInfo_value(sis, 0);
+               srcms = CMS_sign_receipt(si, signer, key, other, flags);
+               if (!srcms)
+                       goto end;
+               CMS_ContentInfo_free(cms);
+               cms = srcms;
+               }
+       else if (operation & SMIME_SIGNERS)
+               {
+               int i;
+               /* If detached data content we enable streaming if
+                * S/MIME output format.
+                */
+               if (operation == SMIME_SIGN)
+                       {
+                               
+                       if (flags & CMS_DETACHED)
+                               {
+                               if (outformat == FORMAT_SMIME)
+                                       flags |= CMS_STREAM;
+                               }
+                       flags |= CMS_PARTIAL;
+                       cms = CMS_sign(NULL, NULL, other, in, flags);
+                       if (!cms)
+                               goto end;
+                       if (econtent_type)
+                               CMS_set1_eContentType(cms, econtent_type);
+
+                       if (rr_to)
+                               {
+                               rr = make_receipt_request(rr_to, rr_allorfirst,
+                                                               rr_from);
+                               if (!rr)
+                                       {
+                                       BIO_puts(bio_err,
+                               "Signed Receipt Request Creation Error\n");
+                                       goto end;
+                                       }
+                               }
+                       }
+               else
+                       flags |= CMS_REUSE_DIGEST;
+               for (i = 0; i < sk_num(sksigners); i++)
+                       {
+                       CMS_SignerInfo *si;
+                       signerfile = sk_value(sksigners, i);
+                       keyfile = sk_value(skkeys, i);
+                       signer = load_cert(bio_err, signerfile,FORMAT_PEM, NULL,
+                                       e, "signer certificate");
+                       if (!signer)
+                               goto end;
+                       key = load_key(bio_err, keyfile, keyform, 0, passin, e,
+                              "signing key file");
+                       if (!key)
+                               goto end;
+                       si = CMS_add1_signer(cms, signer, key, sign_md, flags);
+                       if (!si)
+                               goto end;
+                       if (rr && !CMS_add1_ReceiptRequest(si, rr))
+                               goto end;
+                       X509_free(signer);
+                       signer = NULL;
+                       EVP_PKEY_free(key);
+                       key = NULL;
+                       }
+               /* If not streaming or resigning finalize structure */
+               if ((operation == SMIME_SIGN) && !(flags & CMS_STREAM))
+                       {
+                       if (!CMS_final(cms, in, NULL, flags))
+                               goto end;
+                       }
+               }
+
+       if (!cms)
+               {
+               BIO_printf(bio_err, "Error creating CMS structure\n");
+               goto end;
+               }
+
+       ret = 4;
+       if (operation == SMIME_DECRYPT)
+               {
+
+               if (secret_key)
+                       {
+                       if (!CMS_decrypt_set1_key(cms,
+                                               secret_key, secret_keylen,
+                                               secret_keyid, secret_keyidlen))
+                               {
+                               BIO_puts(bio_err,
+                                       "Error decrypting CMS using secret key\n");
+                               goto end;
+                               }
+                       }
+
+               if (key)
+                       {
+                       if (!CMS_decrypt_set1_pkey(cms, key, recip))
+                               {
+                               BIO_puts(bio_err,
+                                       "Error decrypting CMS using private key\n");
+                               goto end;
+                               }
+                       }
+
+               if (!CMS_decrypt(cms, NULL, NULL, indata, out, flags))
+                       {
+                       BIO_printf(bio_err, "Error decrypting CMS structure\n");
+                       goto end;
+                       }
+               }
+       else if (operation == SMIME_DATAOUT)
+               {
+               if (!CMS_data(cms, out, flags))
+                       goto end;
+               }
+       else if (operation == SMIME_UNCOMPRESS)
+               {
+               if (!CMS_uncompress(cms, indata, out, flags))
+                       goto end;
+               }
+       else if (operation == SMIME_DIGEST_VERIFY)
+               {
+               if (CMS_digest_verify(cms, indata, out, flags) > 0)
+                       BIO_printf(bio_err, "Verification successful\n");
+               else
+                       {
+                       BIO_printf(bio_err, "Verification failure\n");
+                       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)
+                       BIO_printf(bio_err, "Verification successful\n");
+               else
+                       {
+                       BIO_printf(bio_err, "Verification failure\n");
+                       goto end;
+                       }
+               if (signerfile)
+                       {
+                       STACK_OF(X509) *signers;
+                       signers = CMS_get0_signers(cms);
+                       if (!save_certs(signerfile, signers))
+                               {
+                               BIO_printf(bio_err,
+                                               "Error writing signers to %s\n",
+                                                               signerfile);
+                               ret = 5;
+                               goto end;
+                               }
+                       sk_X509_free(signers);
+                       }
+               if (rr_print)
+                       receipt_request_print(bio_err, cms);
+                                       
+               }
+       else if (operation == SMIME_VERIFY_RECEIPT)
+               {
+               if (CMS_verify_receipt(rcms, cms, other, store, flags) > 0)
+                       BIO_printf(bio_err, "Verification successful\n");
+               else
+                       {
+                       BIO_printf(bio_err, "Verification failure\n");
+                       goto end;
+                       }
+               }
+       else
+               {
+               if (outformat == FORMAT_SMIME)
+                       {
+                       if (to)
+                               BIO_printf(out, "To: %s\n", to);
+                       if (from)
+                               BIO_printf(out, "From: %s\n", from);
+                       if (subject)
+                               BIO_printf(out, "Subject: %s\n", subject);
+                       if (operation == SMIME_RESIGN)
+                               ret = SMIME_write_CMS(out, cms, indata, flags);
+                       else
+                               ret = SMIME_write_CMS(out, cms, in, flags);
+                       }
+               else if (outformat == FORMAT_PEM) 
+                       ret = PEM_write_bio_CMS(out, cms);
+               else if (outformat == FORMAT_ASN1) 
+                       ret = i2d_CMS_bio(out,cms);
+               else
+                       {
+                       BIO_printf(bio_err, "Bad output format for CMS file\n");
+                       goto end;
+                       }
+               if (ret <= 0)
+                       {
+                       ret = 6;
+                       goto end;
+                       }
+               }
+       ret = 0;
+end:
+       if (ret)
+               ERR_print_errors(bio_err);
+       if (need_rand)
+               app_RAND_write_file(NULL, bio_err);
+       sk_X509_pop_free(encerts, X509_free);
+       sk_X509_pop_free(other, X509_free);
+       if (vpm)
+               X509_VERIFY_PARAM_free(vpm);
+       if (sksigners)
+               sk_free(sksigners);
+       if (skkeys)
+               sk_free(skkeys);
+       if (secret_key)
+               OPENSSL_free(secret_key);
+       if (secret_keyid)
+               OPENSSL_free(secret_keyid);
+       if (econtent_type)
+               ASN1_OBJECT_free(econtent_type);
+       if (rr)
+               CMS_ReceiptRequest_free(rr);
+       if (rr_to)
+               sk_free(rr_to);
+       if (rr_from)
+               sk_free(rr_from);
+       X509_STORE_free(store);
+       X509_free(cert);
+       X509_free(recip);
+       X509_free(signer);
+       EVP_PKEY_free(key);
+       CMS_ContentInfo_free(cms);
+       CMS_ContentInfo_free(rcms);
+       BIO_free(rctin);
+       BIO_free(in);
+       BIO_free(indata);
+       BIO_free_all(out);
+       if (passin) OPENSSL_free(passin);
+       return (ret);
+}
+
+static int save_certs(char *signerfile, STACK_OF(X509) *signers)
+       {
+       int i;
+       BIO *tmp;
+       if (!signerfile)
+               return 1;
+       tmp = BIO_new_file(signerfile, "w");
+       if (!tmp) return 0;
+       for(i = 0; i < sk_X509_num(signers); i++)
+               PEM_write_bio_X509(tmp, sk_X509_value(signers, i));
+       BIO_free(tmp);
+       return 1;
+       }
+       
+
+/* Minimal callback just to output policy info (if any) */
+
+static int cms_cb(int ok, X509_STORE_CTX *ctx)
+       {
+       int error;
+
+       error = X509_STORE_CTX_get_error(ctx);
+
+       if ((error != X509_V_ERR_NO_EXPLICIT_POLICY)
+               && ((error != X509_V_OK) || (ok != 2)))
+               return ok;
+
+       policies_print(NULL, ctx);
+
+       return ok;
+
+       }
+
+static void gnames_stack_print(BIO *out, STACK_OF(GENERAL_NAMES) *gns)
+       {
+       STACK_OF(GENERAL_NAME) *gens;
+       GENERAL_NAME *gen;
+       int i, j;
+       for (i = 0; i < sk_GENERAL_NAMES_num(gns); i++)
+               {
+               gens = sk_GENERAL_NAMES_value(gns, i);
+               for (j = 0; j < sk_GENERAL_NAME_num(gens); j++)
+                       {
+                       gen = sk_GENERAL_NAME_value(gens, j);
+                       BIO_puts(out, "    ");
+                       GENERAL_NAME_print(out, gen);
+                       BIO_puts(out, "\n");
+                       }
+               }
+       return;
+       }
+
+static void receipt_request_print(BIO *out, CMS_ContentInfo *cms)
+       {
+       STACK_OF(CMS_SignerInfo) *sis;
+       CMS_SignerInfo *si;
+       CMS_ReceiptRequest *rr;
+       int allorfirst;
+       STACK_OF(GENERAL_NAMES) *rto, *rlist;
+       ASN1_STRING *scid;
+       int i, rv;
+       sis = CMS_get0_SignerInfos(cms);
+       for (i = 0; i < sk_CMS_SignerInfo_num(sis); i++)
+               {
+               si = sk_CMS_SignerInfo_value(sis, i);
+               rv = CMS_get1_ReceiptRequest(si, &rr);
+               BIO_printf(bio_err, "Signer %d:\n", i + 1);
+               if (rv == 0)
+                       BIO_puts(bio_err, "  No Receipt Request\n");
+               else if (rv < 0)
+                       {
+                       BIO_puts(bio_err, "  Receipt Request Parse Error\n");
+                       ERR_print_errors(bio_err);
+                       }
+               else
+                       {
+                       char *id;
+                       int idlen;
+                       CMS_ReceiptRequest_get0_values(rr, &scid, &allorfirst,
+                                                       &rlist, &rto);
+                       BIO_puts(out, "  Signed Content ID:\n");
+                       idlen = ASN1_STRING_length(scid);
+                       id = (char *)ASN1_STRING_data(scid);
+                       BIO_dump_indent(out, id, idlen, 4);
+                       BIO_puts(out, "  Receipts From");
+                       if (rlist)
+                               {
+                               BIO_puts(out, " List:\n");
+                               gnames_stack_print(out, rlist);
+                               }
+                       else if (allorfirst == 1)
+                               BIO_puts(out, ": First Tier\n");
+                       else if (allorfirst == 0)
+                               BIO_puts(out, ": All\n");
+                       else
+                               BIO_printf(out, " Unknown (%d)\n", allorfirst);
+                       BIO_puts(out, "  Receipts To:\n");
+                       gnames_stack_print(out, rto);
+                       }
+               if (rr)
+                       CMS_ReceiptRequest_free(rr);
+               }
+       }
+
+static STACK_OF(GENERAL_NAMES) *make_names_stack(STACK *ns)
+       {
+       int i;
+       STACK_OF(GENERAL_NAMES) *ret;
+       GENERAL_NAMES *gens = NULL;
+       GENERAL_NAME *gen = NULL;
+       ret = sk_GENERAL_NAMES_new_null();
+       if (!ret)
+               goto err;
+       for (i = 0; i < sk_num(ns); i++)
+               {
+               CONF_VALUE cnf;
+               cnf.name = "email";
+               cnf.value = sk_value(ns, i);
+               gen = v2i_GENERAL_NAME(NULL, NULL, &cnf);
+               if (!gen)
+                       goto err;
+               gens = GENERAL_NAMES_new();
+               if (!gens)
+                       goto err;
+               if (!sk_GENERAL_NAME_push(gens, gen))
+                       goto err;
+               gen = NULL;
+               if (!sk_GENERAL_NAMES_push(ret, gens))
+                       goto err;
+               gens = NULL;
+               }
+
+       return ret;
+
+       err:
+       if (ret)
+               sk_GENERAL_NAMES_pop_free(ret, GENERAL_NAMES_free);
+       if (gens)
+               GENERAL_NAMES_free(gens);
+       if (gen)
+               GENERAL_NAME_free(gen);
+       return NULL;
+       }
+
+
+static CMS_ReceiptRequest *make_receipt_request(STACK *rr_to, int rr_allorfirst,
+                                                               STACK *rr_from)
+       {
+       STACK_OF(GENERAL_NAMES) *rct_to, *rct_from;
+       CMS_ReceiptRequest *rr;
+       rct_to = make_names_stack(rr_to);
+       if (!rct_to)
+               goto err;
+       if (rr_from)
+               {
+               rct_from = make_names_stack(rr_from);
+               if (!rct_from)
+                       goto err;
+               }
+       else
+               rct_from = NULL;
+       rr = CMS_ReceiptRequest_create0(NULL, -1, rr_allorfirst, rct_from,
+                                               rct_to);
+       return rr;
+       err:
+       return NULL;
+       }
+
+#endif
index 75ddec3..c5ecf93 100644 (file)
@@ -190,6 +190,8 @@ int MAIN(int argc, char **argv)
                        out_bin = 1;
                else if (strcmp(*argv,"-d") == 0)
                        debug=1;
+               else if (!strcmp(*argv,"-fips-fingerprint"))
+                       hmac_key = "etaonrishdlcupfm";
                else if (!strcmp(*argv,"-hmac"))
                        {
                        if (--argc < 1)
@@ -227,6 +229,7 @@ int MAIN(int argc, char **argv)
                BIO_printf(bio_err,"-keyform arg    key file format (PEM or ENGINE)\n");
                BIO_printf(bio_err,"-signature file signature to verify\n");
                BIO_printf(bio_err,"-binary         output in binary form\n");
+               BIO_printf(bio_err,"-hmac key       create hashed MAC with key\n");
 #ifndef OPENSSL_NO_ENGINE
                BIO_printf(bio_err,"-engine e       use engine e, possibly a hardware device.\n");
 #endif
index c63437f..771e15f 100644 (file)
@@ -244,7 +244,7 @@ bad:
                                " the ec parameters are encoded\n");
                BIO_printf(bio_err, "                 in the asn1 der "
                                "encoding\n");
-               BIO_printf(bio_err, "                 possilbe values:"
+               BIO_printf(bio_err, "                 possible values:"
                                " named_curve (default)\n");
                BIO_printf(bio_err,"                                  "
                                "explicit\n");
index 3dc36c4..1001f3b 100644 (file)
  *
  */
 #ifndef OPENSSL_NO_OCSP
-
+#define USE_SOCKETS
 #include <stdio.h>
+#include <stdlib.h>
 #include <string.h>
-#include "apps.h"
-#include <openssl/pem.h>
-#include <openssl/ocsp.h>
-#include <openssl/err.h>
+#include "apps.h" /* needs to be included before the openssl headers! */
+#include <openssl/e_os2.h>
 #include <openssl/ssl.h>
-#include <openssl/bn.h>
+#include <openssl/err.h>
 
 /* Maximum leeway in validity period: default 5 minutes */
 #define MAX_VALIDITY_PERIOD    (5 * 60)
@@ -86,6 +85,8 @@ static char **lookup_serial(CA_DB *db, ASN1_INTEGER *ser);
 static BIO *init_responder(char *port);
 static int do_responder(OCSP_REQUEST **preq, BIO **pcbio, BIO *acbio, char *port);
 static int send_ocsp_response(BIO *cbio, OCSP_RESPONSE *resp);
+static OCSP_RESPONSE *query_responder(BIO *err, BIO *cbio, char *path,
+                               OCSP_REQUEST *req, int req_timeout);
 
 #undef PROG
 #define PROG ocsp_main
@@ -112,11 +113,11 @@ int MAIN(int argc, char **argv)
        BIO *acbio = NULL, *cbio = NULL;
        BIO *derbio = NULL;
        BIO *out = NULL;
+       int req_timeout = -1;
        int req_text = 0, resp_text = 0;
        long nsec = MAX_VALIDITY_PERIOD, maxage = -1;
        char *CAfile = NULL, *CApath = NULL;
        X509_STORE *store = NULL;
-       SSL_CTX *ctx = NULL;
        STACK_OF(X509) *sign_other = NULL, *verify_other = NULL, *rother = NULL;
        char *sign_certfile = NULL, *verify_certfile = NULL, *rcertfile = NULL;
        unsigned long sign_flags = 0, verify_flags = 0, rflags = 0;
@@ -154,6 +155,22 @@ int MAIN(int argc, char **argv)
                                }
                        else badarg = 1;
                        }
+               else if (!strcmp(*args, "-timeout"))
+                       {
+                       if (args[1])
+                               {
+                               args++;
+                               req_timeout = atol(*args);
+                               if (req_timeout < 0)
+                                       {
+                                       BIO_printf(bio_err,
+                                               "Illegal timeout value %s\n",
+                                               *args);
+                                       badarg = 1;
+                                       }
+                               }
+                       else badarg = 1;
+                       }
                else if (!strcmp(*args, "-url"))
                        {
                        if (args[1])
@@ -703,52 +720,14 @@ int MAIN(int argc, char **argv)
        else if (host)
                {
 #ifndef OPENSSL_NO_SOCK
-               cbio = BIO_new_connect(host);
+               resp = process_responder(bio_err, req, host, path,
+                                               port, use_ssl, req_timeout);
+               if (!resp)
+                       goto end;
 #else
                BIO_printf(bio_err, "Error creating connect BIO - sockets not supported.\n");
                goto end;
 #endif
-               if (!cbio)
-                       {
-                       BIO_printf(bio_err, "Error creating connect BIO\n");
-                       goto end;
-                       }
-               if (port) BIO_set_conn_port(cbio, port);
-               if (use_ssl == 1)
-                       {
-                       BIO *sbio;
-#if !defined(OPENSSL_NO_SSL2) && !defined(OPENSSL_NO_SSL3)
-                       ctx = SSL_CTX_new(SSLv23_client_method());
-#elif !defined(OPENSSL_NO_SSL3)
-                       ctx = SSL_CTX_new(SSLv3_client_method());
-#elif !defined(OPENSSL_NO_SSL2)
-                       ctx = SSL_CTX_new(SSLv2_client_method());
-#else
-                       BIO_printf(bio_err, "SSL is disabled\n");
-                       goto end;
-#endif
-                       if (ctx == NULL)
-                               {
-                               BIO_printf(bio_err, "Error creating SSL context.\n");
-                               goto end;
-                               }
-                       SSL_CTX_set_mode(ctx, SSL_MODE_AUTO_RETRY);
-                       sbio = BIO_new_ssl(ctx, 1);
-                       cbio = BIO_push(sbio, cbio);
-                       }
-               if (BIO_do_connect(cbio) <= 0)
-                       {
-                       BIO_printf(bio_err, "Error connecting BIO\n");
-                       goto end;
-                       }
-               resp = OCSP_sendreq_bio(cbio, path, req);
-               BIO_free_all(cbio);
-               cbio = NULL;
-               if (!resp)
-                       {
-                       BIO_printf(bio_err, "Error querying OCSP responsder\n");
-                       goto end;
-                       }
                }
        else if (respin)
                {
@@ -897,7 +876,6 @@ end:
                OPENSSL_free(host);
                OPENSSL_free(port);
                OPENSSL_free(path);
-               SSL_CTX_free(ctx);
                }
 
        OPENSSL_EXIT(ret);
@@ -1121,6 +1099,7 @@ static char **lookup_serial(CA_DB *db, ASN1_INTEGER *ser)
        char *itmp, *row[DB_NUMBER],**rrow;
        for (i = 0; i < DB_NUMBER; i++) row[i] = NULL;
        bn = ASN1_INTEGER_to_BN(ser,NULL);
+       OPENSSL_assert(bn); /* FIXME: should report an error at this point and abort */
        if (BN_is_zero(bn))
                itmp = BUF_strdup("00");
        else
@@ -1231,4 +1210,137 @@ static int send_ocsp_response(BIO *cbio, OCSP_RESPONSE *resp)
        return 1;
        }
 
+static OCSP_RESPONSE *query_responder(BIO *err, BIO *cbio, char *path,
+                               OCSP_REQUEST *req, int req_timeout)
+       {
+       int fd;
+       int rv;
+       OCSP_REQ_CTX *ctx = NULL;
+       OCSP_RESPONSE *rsp = NULL;
+       fd_set confds;
+       struct timeval tv;
+
+       if (req_timeout != -1)
+               BIO_set_nbio(cbio, 1);
+
+       rv = BIO_do_connect(cbio);
+
+       if ((rv <= 0) && ((req_timeout == -1) || !BIO_should_retry(cbio)))
+               {
+               BIO_puts(err, "Error connecting BIO\n");
+               return NULL;
+               }
+
+       if (req_timeout == -1)
+               return OCSP_sendreq_bio(cbio, path, req);
+
+       if (BIO_get_fd(cbio, &fd) <= 0)
+               {
+               BIO_puts(err, "Can't get connection fd\n");
+               goto err;
+               }
+
+       if (rv <= 0)
+               {
+               FD_ZERO(&confds);
+               openssl_fdset(fd, &confds);
+               tv.tv_usec = 0;
+               tv.tv_sec = req_timeout;
+               rv = select(fd + 1, NULL, (void *)&confds, NULL, &tv);
+               if (rv == 0)
+                       {
+                       BIO_puts(err, "Timeout on connect\n");
+                       return NULL;
+                       }
+               }
+
+
+       ctx = OCSP_sendreq_new(cbio, path, req, -1);
+       if (!ctx)
+               return NULL;
+       
+       for (;;)
+               {
+               rv = OCSP_sendreq_nbio(&rsp, ctx);
+               if (rv != -1)
+                       break;
+               FD_ZERO(&confds);
+               openssl_fdset(fd, &confds);
+               tv.tv_usec = 0;
+               tv.tv_sec = req_timeout;
+               if (BIO_should_read(cbio))
+                       rv = select(fd + 1, (void *)&confds, NULL, NULL, &tv);
+               else if (BIO_should_write(cbio))
+                       rv = select(fd + 1, NULL, (void *)&confds, NULL, &tv);
+               else
+                       {
+                       BIO_puts(err, "Unexpected retry condition\n");
+                       goto err;
+                       }
+               if (rv == 0)
+                       {
+                       BIO_puts(err, "Timeout on request\n");
+                       break;
+                       }
+               if (rv == -1)
+                       {
+                       BIO_puts(err, "Select error\n");
+                       break;
+                       }
+                       
+               }
+       err:
+       if (ctx)
+               OCSP_REQ_CTX_free(ctx);
+
+       return rsp;
+       }
+
+OCSP_RESPONSE *process_responder(BIO *err, OCSP_REQUEST *req,
+                       char *host, char *path, char *port, int use_ssl,
+                       int req_timeout)
+       {
+       BIO *cbio = NULL;
+       SSL_CTX *ctx = NULL;
+       OCSP_RESPONSE *resp = NULL;
+       cbio = BIO_new_connect(host);
+       if (!cbio)
+               {
+               BIO_printf(err, "Error creating connect BIO\n");
+               goto end;
+               }
+       if (port) BIO_set_conn_port(cbio, port);
+       if (use_ssl == 1)
+               {
+               BIO *sbio;
+#if !defined(OPENSSL_NO_SSL2) && !defined(OPENSSL_NO_SSL3)
+               ctx = SSL_CTX_new(SSLv23_client_method());
+#elif !defined(OPENSSL_NO_SSL3)
+               ctx = SSL_CTX_new(SSLv3_client_method());
+#elif !defined(OPENSSL_NO_SSL2)
+               ctx = SSL_CTX_new(SSLv2_client_method());
+#else
+               BIO_printf(err, "SSL is disabled\n");
+                       goto end;
+#endif
+               if (ctx == NULL)
+                       {
+                       BIO_printf(err, "Error creating SSL context.\n");
+                       goto end;
+                       }
+               SSL_CTX_set_mode(ctx, SSL_MODE_AUTO_RETRY);
+               sbio = BIO_new_ssl(ctx, 1);
+               cbio = BIO_push(sbio, cbio);
+               }
+       resp = query_responder(err, cbio, path, req, req_timeout);
+       if (!resp)
+               BIO_printf(bio_err, "Error querying OCSP responsder\n");
+       end:
+       if (ctx)
+               SSL_CTX_free(ctx);
+       if (cbio)
+               BIO_free_all(cbio);
+       return resp;
+       }
+
 #endif
index 89e1e05..aafd800 100644 (file)
@@ -28,6 +28,7 @@ extern int speed_main(int argc,char *argv[]);
 extern int s_time_main(int argc,char *argv[]);
 extern int version_main(int argc,char *argv[]);
 extern int pkcs7_main(int argc,char *argv[]);
+extern int cms_main(int argc,char *argv[]);
 extern int crl2pkcs7_main(int argc,char *argv[]);
 extern int sess_id_main(int argc,char *argv[]);
 extern int ciphers_main(int argc,char *argv[]);
@@ -109,6 +110,9 @@ FUNCTION functions[] = {
 #endif
        {FUNC_TYPE_GENERAL,"version",version_main},
        {FUNC_TYPE_GENERAL,"pkcs7",pkcs7_main},
+#ifndef OPENSSL_NO_CMS
+       {FUNC_TYPE_GENERAL,"cms",cms_main},
+#endif
        {FUNC_TYPE_GENERAL,"crl2pkcs7",crl2pkcs7_main},
        {FUNC_TYPE_GENERAL,"sess_id",sess_id_main},
 #if !defined(OPENSSL_NO_SOCK) && !(defined(OPENSSL_NO_SSL2) && defined(OPENSSL_NO_SSL3))
index f58e65e..5ed0896 100644 (file)
@@ -719,8 +719,7 @@ bad:
                           message */
                        goto end;
                        }
-               if (EVP_PKEY_type(pkey->type) == EVP_PKEY_DSA || 
-                       EVP_PKEY_type(pkey->type) == EVP_PKEY_EC)
+               else
                        {
                        char *randfile = NCONF_get_string(req_conf,SECTION,"RANDFILE");
                        if (randfile == NULL)
index 4638909..f3c458e 100644 (file)
@@ -119,24 +119,36 @@ int MAIN(int argc, char **argv)
        while(argc >= 1)
        {
                if (!strcmp(*argv,"-in")) {
-                       if (--argc < 1) badarg = 1;
-                        infile= *(++argv);
+                       if (--argc < 1)
+                               badarg = 1;
+                       else
+                               infile= *(++argv);
                } else if (!strcmp(*argv,"-out")) {
-                       if (--argc < 1) badarg = 1;
-                       outfile= *(++argv);
+                       if (--argc < 1)
+                               badarg = 1;
+                       else
+                               outfile= *(++argv);
                } else if(!strcmp(*argv, "-inkey")) {
-                       if (--argc < 1) badarg = 1;
-                       keyfile = *(++argv);
+                       if (--argc < 1)
+                               badarg = 1;
+                       else
+                               keyfile = *(++argv);
                } else if (!strcmp(*argv,"-passin")) {
-                       if (--argc < 1) badarg = 1;
-                       passargin= *(++argv);
+                       if (--argc < 1)
+                               badarg = 1;
+                       else
+                               passargin= *(++argv);
                } else if (strcmp(*argv,"-keyform") == 0) {
-                       if (--argc < 1) badarg = 1;
-                       keyform=str2fmt(*(++argv));
+                       if (--argc < 1)
+                               badarg = 1;
+                       else
+                               keyform=str2fmt(*(++argv));
 #ifndef OPENSSL_NO_ENGINE
                } else if(!strcmp(*argv, "-engine")) {
-                       if (--argc < 1) badarg = 1;
-                       engine = *(++argv);
+                       if (--argc < 1)
+                               badarg = 1;
+                       else
+                               engine = *(++argv);
 #endif
                } else if(!strcmp(*argv, "-pubin")) {
                        key_type = KEY_PUBKEY;
index d240fe2..a4983c1 100644 (file)
@@ -134,6 +134,7 @@ typedef unsigned int u_int;
 #include <openssl/err.h>
 #include <openssl/pem.h>
 #include <openssl/rand.h>
+#include <openssl/ocsp.h>
 #include "s_apps.h"
 #include "timeouts.h"
 
@@ -173,12 +174,16 @@ static int c_Pause=0;
 static int c_debug=0;
 #ifndef OPENSSL_NO_TLSEXT
 static int c_tlsextdebug=0;
+static int c_status_req=0;
 #endif
 static int c_msg=0;
 static int c_showcerts=0;
 
 static void sc_usage(void);
 static void print_stuff(BIO *berr,SSL *con,int full);
+#ifndef OPENSSL_NO_TLSEXT
+static int ocsp_resp_cb(SSL *s, void *arg);
+#endif
 static BIO *bio_c_out=NULL;
 static int c_quiet=0;
 static int c_ign_eof=0;
@@ -239,6 +244,7 @@ static void sc_usage(void)
 #ifndef OPENSSL_NO_TLSEXT
        BIO_printf(bio_err," -servername host  - Set TLS extension servername in ClientHello\n");
        BIO_printf(bio_err," -tlsextdebug      - hex dump of all TLS extensions received\n");
+       BIO_printf(bio_err," -status           - request certificate status from server\n");
        BIO_printf(bio_err," -no_ticket        - disable use of RFC4507bis session tickets\n");
 #endif
        }
@@ -435,6 +441,8 @@ int MAIN(int argc, char **argv)
 #ifndef OPENSSL_NO_TLSEXT
                else if (strcmp(*argv,"-tlsextdebug") == 0)
                        c_tlsextdebug=1;
+               else if (strcmp(*argv,"-status") == 0)
+                       c_status_req=1;
 #endif
 #ifdef WATT32
                else if (strcmp(*argv,"-wdebug") == 0)
@@ -826,6 +834,23 @@ re_start:
                SSL_set_tlsext_debug_callback(con, tlsext_cb);
                SSL_set_tlsext_debug_arg(con, bio_c_out);
                }
+       if (c_status_req)
+               {
+               SSL_set_tlsext_status_type(con, TLSEXT_STATUSTYPE_ocsp);
+               SSL_CTX_set_tlsext_status_cb(ctx, ocsp_resp_cb);
+               SSL_CTX_set_tlsext_status_arg(ctx, bio_c_out);
+#if 0
+{
+STACK_OF(OCSP_RESPID) *ids = sk_OCSP_RESPID_new_null();
+OCSP_RESPID *id = OCSP_RESPID_new();
+id->value.byKey = ASN1_OCTET_STRING_new();
+id->type = V_OCSP_RESPID_KEY;
+ASN1_STRING_set(id->value.byKey, "Hello World", -1);
+sk_OCSP_RESPID_push(ids, id);
+SSL_set_tlsext_status_ids(con, ids);
+}
+#endif
+               }
 #endif
 
        SSL_set_bio(con,sbio,sbio);
@@ -1430,3 +1455,31 @@ static void print_stuff(BIO *bio, SSL *s, int full)
        (void)BIO_flush(bio);
        }
 
+#ifndef OPENSSL_NO_TLSEXT
+
+static int ocsp_resp_cb(SSL *s, void *arg)
+       {
+       const unsigned char *p;
+       int len;
+       OCSP_RESPONSE *rsp;
+       len = SSL_get_tlsext_status_ocsp_resp(s, &p);
+       BIO_puts(arg, "OCSP response: ");
+       if (!p)
+               {
+               BIO_puts(arg, "no response sent\n");
+               return 1;
+               }
+       rsp = d2i_OCSP_RESPONSE(NULL, &p, len);
+       if (!rsp)
+               {
+               BIO_puts(arg, "response parse error\n");
+               BIO_dump_indent(arg, (char *)p, len, 4);
+               return 0;
+               }
+       BIO_puts(arg, "\n======================================\n");
+       OCSP_RESPONSE_print(arg, rsp, 0);
+       BIO_puts(arg, "======================================\n");
+       OCSP_RESPONSE_free(rsp);
+       return 1;
+       }
+#endif  /* ndef OPENSSL_NO_TLSEXT */
index 7c5775f..7919c43 100644 (file)
@@ -153,6 +153,7 @@ typedef unsigned int u_int;
 #include <openssl/x509.h>
 #include <openssl/ssl.h>
 #include <openssl/rand.h>
+#include <openssl/ocsp.h>
 #ifndef OPENSSL_NO_DH
 #include <openssl/dh.h>
 #endif
@@ -269,6 +270,8 @@ static BIO *bio_s_out=NULL;
 static int s_debug=0;
 #ifndef OPENSSL_NO_TLSEXT
 static int s_tlsextdebug=0;
+static int s_tlsextstatus=0;
+static int cert_status_cb(SSL *s, void *arg);
 #endif
 static int s_msg=0;
 static int s_quiet=0;
@@ -330,6 +333,11 @@ static void sv_usage(void)
        BIO_printf(bio_err," -Verify arg   - turn on peer certificate verification, must have a cert.\n");
        BIO_printf(bio_err," -cert arg     - certificate file to use\n");
        BIO_printf(bio_err,"                 (default is %s)\n",TEST_CERT);
+       BIO_printf(bio_err," -crl_check    - check the peer certificate has not been revoked by its CA.\n" \
+                          "                 The CRL(s) are appended to the certificate file\n");
+       BIO_printf(bio_err," -crl_check_all - check the peer certificate has not been revoked by its CA\n" \
+                          "                 or any other CRL in the CA chain. CRL(s) are appened to the\n" \
+                          "                 the certificate file.\n");
        BIO_printf(bio_err," -certform arg - certificate format (PEM or DER) PEM default\n");
        BIO_printf(bio_err," -key arg      - Private Key file to use, in cert file if\n");
        BIO_printf(bio_err,"                 not specified (default is %s)\n",TEST_CERT);
@@ -585,6 +593,152 @@ static int MS_CALLBACK ssl_servername_cb(SSL *s, int *ad, void *arg)
                }
        return SSL_TLSEXT_ERR_OK;
 }
+
+/* Structure passed to cert status callback */
+
+typedef struct tlsextstatusctx_st {
+   /* Default responder to use */
+   char *host, *path, *port;
+   int use_ssl;
+   int timeout;
+   BIO *err;
+   int verbose;
+} tlsextstatusctx;
+
+static tlsextstatusctx tlscstatp = {NULL, NULL, NULL, 0, -1, NULL, 0};
+
+/* Certificate Status callback. This is called when a client includes a
+ * certificate status request extension.
+ *
+ * This is a simplified version. It examines certificates each time and
+ * makes one OCSP responder query for each request.
+ *
+ * A full version would store details such as the OCSP certificate IDs and
+ * minimise the number of OCSP responses by caching them until they were
+ * considered "expired".
+ */
+
+static int cert_status_cb(SSL *s, void *arg)
+       {
+       tlsextstatusctx *srctx = arg;
+       BIO *err = srctx->err;
+       char *host, *port, *path;
+       int use_ssl;
+       unsigned char *rspder = NULL;
+       int rspderlen;
+       STACK *aia = NULL;
+       X509 *x = NULL;
+       X509_STORE_CTX inctx;
+       X509_OBJECT obj;
+       OCSP_REQUEST *req = NULL;
+       OCSP_RESPONSE *resp = NULL;
+       OCSP_CERTID *id = NULL;
+       STACK_OF(X509_EXTENSION) *exts;
+       int ret = SSL_TLSEXT_ERR_NOACK;
+       int i;
+#if 0
+STACK_OF(OCSP_RESPID) *ids;
+SSL_get_tlsext_status_ids(s, &ids);
+BIO_printf(err, "cert_status: received %d ids\n", sk_OCSP_RESPID_num(ids));
+#endif
+       if (srctx->verbose)
+               BIO_puts(err, "cert_status: callback called\n");
+       /* Build up OCSP query from server certificate */
+       x = SSL_get_certificate(s);
+       aia = X509_get1_ocsp(x);
+       if (aia)
+               {
+               if (!OCSP_parse_url(sk_value(aia, 0),
+                       &host, &port, &path, &use_ssl))
+                       {
+                       BIO_puts(err, "cert_status: can't parse AIA URL\n");
+                       goto err;
+                       }
+               if (srctx->verbose)
+                       BIO_printf(err, "cert_status: AIA URL: %s\n",
+                                       sk_value(aia, 0));
+               }
+       else
+               {
+               if (!srctx->host)
+                       {
+                       BIO_puts(srctx->err, "cert_status: no AIA and no default responder URL\n");
+                       goto done;
+                       }
+               host = srctx->host;
+               path = srctx->path;
+               port = srctx->port;
+               use_ssl = srctx->use_ssl;
+               }
+               
+       if (!X509_STORE_CTX_init(&inctx,
+                               SSL_CTX_get_cert_store(SSL_get_SSL_CTX(s)),
+                               NULL, NULL))
+               goto err;
+       if (X509_STORE_get_by_subject(&inctx,X509_LU_X509,
+                               X509_get_issuer_name(x),&obj) <= 0)
+               {
+               BIO_puts(err, "cert_status: Can't retrieve issuer certificate.\n");
+               X509_STORE_CTX_cleanup(&inctx);
+               goto done;
+               }
+       req = OCSP_REQUEST_new();
+       if (!req)
+               goto err;
+       id = OCSP_cert_to_id(NULL, x, obj.data.x509);
+       X509_free(obj.data.x509);
+       X509_STORE_CTX_cleanup(&inctx);
+       if (!id)
+               goto err;
+       if (!OCSP_request_add0_id(req, id))
+               goto err;
+       id = NULL;
+       /* Add any extensions to the request */
+       SSL_get_tlsext_status_exts(s, &exts);
+       for (i = 0; i < sk_X509_EXTENSION_num(exts); i++)
+               {
+               X509_EXTENSION *ext = sk_X509_EXTENSION_value(exts, i);
+               if (!OCSP_REQUEST_add_ext(req, ext, -1))
+                       goto err;
+               }
+       resp = process_responder(err, req, host, path, port, use_ssl,
+                                       srctx->timeout);
+       if (!resp)
+               {
+               BIO_puts(err, "cert_status: error querying responder\n");
+               goto done;
+               }
+       rspderlen = i2d_OCSP_RESPONSE(resp, &rspder);
+       if (rspderlen <= 0)
+               goto err;
+       SSL_set_tlsext_status_ocsp_resp(s, rspder, rspderlen);
+       if (srctx->verbose)
+               {
+               BIO_puts(err, "cert_status: ocsp response sent:\n");
+               OCSP_RESPONSE_print(err, resp, 2);
+               }
+       ret = SSL_TLSEXT_ERR_OK;
+       done:
+       if (ret != SSL_TLSEXT_ERR_OK)
+               ERR_print_errors(err);
+       if (aia)
+               {
+               OPENSSL_free(host);
+               OPENSSL_free(path);
+               OPENSSL_free(port);
+               X509_email_free(aia);
+               }
+       if (id)
+               OCSP_CERTID_free(id);
+       if (req)
+               OCSP_REQUEST_free(req);
+       if (resp)
+               OCSP_RESPONSE_free(resp);
+       return ret;
+       err:
+       ret = SSL_TLSEXT_ERR_ALERT_FATAL;
+       goto done;
+       }
 #endif
 int MAIN(int, char **);
 
@@ -760,7 +914,7 @@ int MAIN(int argc, char *argv[])
                        {
                        vflags |= X509_V_FLAG_CRL_CHECK;
                        }
-               else if (strcmp(*argv,"-crl_check") == 0)
+               else if (strcmp(*argv,"-crl_check_all") == 0)
                        {
                        vflags |= X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL;
                        }
@@ -792,6 +946,33 @@ int MAIN(int argc, char *argv[])
 #ifndef OPENSSL_NO_TLSEXT
                else if (strcmp(*argv,"-tlsextdebug") == 0)
                        s_tlsextdebug=1;
+               else if (strcmp(*argv,"-status") == 0)
+                       s_tlsextstatus=1;
+               else if (strcmp(*argv,"-status_verbose") == 0)
+                       {
+                       s_tlsextstatus=1;
+                       tlscstatp.verbose = 1;
+                       }
+               else if (!strcmp(*argv, "-status_timeout"))
+                       {
+                       s_tlsextstatus=1;
+                        if (--argc < 1) goto bad;
+                       tlscstatp.timeout = atoi(*(++argv));
+                       }
+               else if (!strcmp(*argv, "-status_url"))
+                       {
+                       s_tlsextstatus=1;
+                        if (--argc < 1) goto bad;
+                       if (!OCSP_parse_url(*(++argv),
+                                       &tlscstatp.host,
+                                       &tlscstatp.port,
+                                       &tlscstatp.path,
+                                       &tlscstatp.use_ssl))
+                               {
+                               BIO_printf(bio_err, "Error parsing URL\n");
+                               goto bad;
+                               }
+                       }
 #endif
                else if (strcmp(*argv,"-msg") == 0)
                        { s_msg=1; }
@@ -1430,6 +1611,12 @@ static int sv_body(char *hostname, int s, unsigned char *context)
                SSL_set_tlsext_debug_callback(con, tlsext_cb);
                SSL_set_tlsext_debug_arg(con, bio_s_out);
                }
+       if (s_tlsextstatus)
+               {
+               SSL_CTX_set_tlsext_status_cb(ctx, cert_status_cb);
+               tlscstatp.err = bio_err;
+               SSL_CTX_set_tlsext_status_arg(ctx, &tlscstatp);
+               }
 #endif
 #ifndef OPENSSL_NO_KRB5
                if ((con->kssl_ctx = kssl_ctx_new()) != NULL)
index 85f559e..8a1974f 100644 (file)
@@ -577,7 +577,7 @@ int MAIN(int argc, char **argv)
 #define MAX_BLOCK_SIZE 64
 #endif
        unsigned char DES_iv[8];
-       unsigned char iv[MAX_BLOCK_SIZE/8];
+       unsigned char iv[2*MAX_BLOCK_SIZE/8];
 #ifndef OPENSSL_NO_DES
        DES_cblock *buf_as_des_cblock = NULL;
        static DES_cblock key ={0x12,0x34,0x56,0x78,0x9a,0xbc,0xde,0xf0};
index 5f61eb5..f693835 100644 (file)
@@ -114,6 +114,7 @@ static const char *x509_usage[]={
 " -alias          - output certificate alias\n",
 " -noout          - no certificate output\n",
 " -ocspid         - print OCSP hash values for the subject name and public key\n",
+" -ocspurl        - print OCSP Responder URL(s)\n",
 " -trustout       - output a \"trusted\" certificate\n",
 " -clrtrust       - clear all trusted purposes\n",
 " -clrreject      - clear all rejected purposes\n",
@@ -179,6 +180,7 @@ int MAIN(int argc, char **argv)
        int next_serial=0;
        int subject_hash=0,issuer_hash=0,ocspid=0;
        int noout=0,sign_flag=0,CA_flag=0,CA_createserial=0,email=0;
+       int ocsp_uri=0;
        int trustout=0,clrtrust=0,clrreject=0,aliasout=0,clrext=0;
        int C=0;
        int x509req=0,days=DEF_DAYS,modulus=0,pubkey=0;
@@ -378,6 +380,8 @@ int MAIN(int argc, char **argv)
                        C= ++num;
                else if (strcmp(*argv,"-email") == 0)
                        email= ++num;
+               else if (strcmp(*argv,"-ocsp_uri") == 0)
+                       ocsp_uri= ++num;
                else if (strcmp(*argv,"-serial") == 0)
                        serial= ++num;
                else if (strcmp(*argv,"-next_serial") == 0)
@@ -731,11 +735,14 @@ bad:
                                ASN1_INTEGER_free(ser);
                                BIO_puts(out, "\n");
                                }
-                       else if (email == i) 
+                       else if ((email == i) || (ocsp_uri == i))
                                {
                                int j;
                                STACK *emlst;
-                               emlst = X509_get1_email(x);
+                               if (email == i)
+                                       emlst = X509_get1_email(x);
+                               else
+                                       emlst = X509_get1_ocsp(x);
                                for (j = 0; j < sk_num(emlst); j++)
                                        BIO_printf(STDout, "%s\n", sk_value(emlst, j));
                                X509_email_free(emlst);
index e6fc44a..baf0222 100644 (file)
@@ -130,6 +130,12 @@ void AES_bi_ige_encrypt(const unsigned char *in, unsigned char *out,
                        const AES_KEY *key2, const unsigned char *ivec,
                        const int enc);
 
+int AES_wrap_key(AES_KEY *key, const unsigned char *iv,
+               unsigned char *out,
+               const unsigned char *in, unsigned int inlen);
+int AES_unwrap_key(AES_KEY *key, const unsigned char *iv,
+               unsigned char *out,
+               const unsigned char *in, unsigned int inlen);
 
 #ifdef  __cplusplus
 }
diff --git a/crypto/openssl-0.9/crypto/aes/aes_wrap.c b/crypto/openssl-0.9/crypto/aes/aes_wrap.c
new file mode 100644 (file)
index 0000000..9feacd6
--- /dev/null
@@ -0,0 +1,259 @@
+/* crypto/aes/aes_wrap.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/aes.h>
+#include <openssl/bio.h>
+
+static const unsigned char default_iv[] = {
+  0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6,
+};
+
+int AES_wrap_key(AES_KEY *key, const unsigned char *iv,
+               unsigned char *out,
+               const unsigned char *in, unsigned int inlen)
+       {
+       unsigned char *A, B[16], *R;
+       unsigned int i, j, t;
+       if ((inlen & 0x7) || (inlen < 8))
+               return -1;
+       A = B;
+       t = 1;
+       memcpy(out + 8, in, inlen);
+       if (!iv)
+               iv = default_iv;
+
+       memcpy(A, iv, 8);
+
+       for (j = 0; j < 6; j++)
+               {
+               R = out + 8;
+               for (i = 0; i < inlen; i += 8, t++, R += 8)
+                       {
+                       memcpy(B + 8, R, 8);
+                       AES_encrypt(B, B, key);
+                       A[7] ^= (unsigned char)(t & 0xff);
+                       if (t > 0xff)   
+                               {
+                               A[6] ^= (unsigned char)((t & 0xff) >> 8);
+                               A[5] ^= (unsigned char)((t & 0xff) >> 16);
+                               A[4] ^= (unsigned char)((t & 0xff) >> 24);
+                               }
+                       memcpy(R, B + 8, 8);
+                       }
+               }
+       memcpy(out, A, 8);
+       return inlen + 8;
+       }
+
+int AES_unwrap_key(AES_KEY *key, const unsigned char *iv,
+               unsigned char *out,
+               const unsigned char *in, unsigned int inlen)
+       {
+       unsigned char *A, B[16], *R;
+       unsigned int i, j, t;
+       inlen -= 8;
+       if (inlen & 0x7)
+               return -1;
+       if (inlen < 8)
+               return -1;
+       A = B;
+       t =  6 * (inlen >> 3);
+       memcpy(A, in, 8);
+       memcpy(out, in + 8, inlen);
+       for (j = 0; j < 6; j++)
+               {
+               R = out + inlen - 8;
+               for (i = 0; i < inlen; i += 8, t--, R -= 8)
+                       {
+                       A[7] ^= (unsigned char)(t & 0xff);
+                       if (t > 0xff)   
+                               {
+                               A[6] ^= (unsigned char)((t & 0xff) >> 8);
+                               A[5] ^= (unsigned char)((t & 0xff) >> 16);
+                               A[4] ^= (unsigned char)((t & 0xff) >> 24);
+                               }
+                       memcpy(B + 8, R, 8);
+                       AES_decrypt(B, B, key);
+                       memcpy(R, B + 8, 8);
+                       }
+               }
+       if (!iv)
+               iv = default_iv;
+       if (memcmp(A, iv, 8))
+               {
+               OPENSSL_cleanse(out, inlen);
+               return 0;
+               }
+       return inlen;
+       }
+
+#ifdef AES_WRAP_TEST
+
+int AES_wrap_unwrap_test(const unsigned char *kek, int keybits,
+                        const unsigned char *iv,
+                        const unsigned char *eout,
+                        const unsigned char *key, int keylen)
+       {
+       unsigned char *otmp = NULL, *ptmp = NULL;
+       int r, ret = 0;
+       AES_KEY wctx;
+       otmp = OPENSSL_malloc(keylen + 8);
+       ptmp = OPENSSL_malloc(keylen);
+       if (!otmp || !ptmp)
+               return 0;
+       if (AES_set_encrypt_key(kek, keybits, &wctx))
+               goto err;
+       r = AES_wrap_key(&wctx, iv, otmp, key, keylen);
+       if (r <= 0)
+               goto err;
+
+       if (eout && memcmp(eout, otmp, keylen))
+               goto err;
+               
+       if (AES_set_decrypt_key(kek, keybits, &wctx))
+               goto err;
+       r = AES_unwrap_key(&wctx, iv, ptmp, otmp, r);
+
+       if (memcmp(key, ptmp, keylen))
+               goto err;
+
+       ret = 1;
+
+       err:
+       if (otmp)
+               OPENSSL_free(otmp);
+       if (ptmp)
+               OPENSSL_free(ptmp);
+
+       return ret;
+
+       }
+
+
+
+int main(int argc, char **argv)
+{
+
+static const unsigned char kek[] = {
+  0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+  0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+  0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+  0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f
+};
+
+static const unsigned char key[] = {
+  0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
+  0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff,
+  0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+  0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f
+};
+
+static const unsigned char e1[] = {
+  0x1f, 0xa6, 0x8b, 0x0a, 0x81, 0x12, 0xb4, 0x47,
+  0xae, 0xf3, 0x4b, 0xd8, 0xfb, 0x5a, 0x7b, 0x82,
+  0x9d, 0x3e, 0x86, 0x23, 0x71, 0xd2, 0xcf, 0xe5
+};
+
+static const unsigned char e2[] = {
+  0x96, 0x77, 0x8b, 0x25, 0xae, 0x6c, 0xa4, 0x35,
+  0xf9, 0x2b, 0x5b, 0x97, 0xc0, 0x50, 0xae, 0xd2,
+  0x46, 0x8a, 0xb8, 0xa1, 0x7a, 0xd8, 0x4e, 0x5d
+};
+
+static const unsigned char e3[] = {
+  0x64, 0xe8, 0xc3, 0xf9, 0xce, 0x0f, 0x5b, 0xa2,
+  0x63, 0xe9, 0x77, 0x79, 0x05, 0x81, 0x8a, 0x2a,
+  0x93, 0xc8, 0x19, 0x1e, 0x7d, 0x6e, 0x8a, 0xe7
+};
+
+static const unsigned char e4[] = {
+  0x03, 0x1d, 0x33, 0x26, 0x4e, 0x15, 0xd3, 0x32,
+  0x68, 0xf2, 0x4e, 0xc2, 0x60, 0x74, 0x3e, 0xdc,
+  0xe1, 0xc6, 0xc7, 0xdd, 0xee, 0x72, 0x5a, 0x93,
+  0x6b, 0xa8, 0x14, 0x91, 0x5c, 0x67, 0x62, 0xd2
+};
+
+static const unsigned char e5[] = {
+  0xa8, 0xf9, 0xbc, 0x16, 0x12, 0xc6, 0x8b, 0x3f,
+  0xf6, 0xe6, 0xf4, 0xfb, 0xe3, 0x0e, 0x71, 0xe4,
+  0x76, 0x9c, 0x8b, 0x80, 0xa3, 0x2c, 0xb8, 0x95,
+  0x8c, 0xd5, 0xd1, 0x7d, 0x6b, 0x25, 0x4d, 0xa1
+};
+
+static const unsigned char e6[] = {
+  0x28, 0xc9, 0xf4, 0x04, 0xc4, 0xb8, 0x10, 0xf4,
+  0xcb, 0xcc, 0xb3, 0x5c, 0xfb, 0x87, 0xf8, 0x26,
+  0x3f, 0x57, 0x86, 0xe2, 0xd8, 0x0e, 0xd3, 0x26,
+  0xcb, 0xc7, 0xf0, 0xe7, 0x1a, 0x99, 0xf4, 0x3b,
+  0xfb, 0x98, 0x8b, 0x9b, 0x7a, 0x02, 0xdd, 0x21
+};
+
+       AES_KEY wctx, xctx;
+       int ret;
+       ret = AES_wrap_unwrap_test(kek, 128, NULL, e1, key, 16);
+       fprintf(stderr, "Key test result %d\n", ret);
+       ret = AES_wrap_unwrap_test(kek, 192, NULL, e2, key, 16);
+       fprintf(stderr, "Key test result %d\n", ret);
+       ret = AES_wrap_unwrap_test(kek, 256, NULL, e3, key, 16);
+       fprintf(stderr, "Key test result %d\n", ret);
+       ret = AES_wrap_unwrap_test(kek, 192, NULL, e4, key, 24);
+       fprintf(stderr, "Key test result %d\n", ret);
+       ret = AES_wrap_unwrap_test(kek, 256, NULL, e5, key, 24);
+       fprintf(stderr, "Key test result %d\n", ret);
+       ret = AES_wrap_unwrap_test(kek, 256, NULL, e6, key, 32);
+       fprintf(stderr, "Key test result %d\n", ret);
+}
+       
+       
+#endif
index a36356e..dc98042 100644 (file)
@@ -62,6 +62,7 @@
 #include <openssl/buffer.h>
 #include <openssl/asn1.h>
 #include <openssl/objects.h>
+#include <openssl/bn.h>
 
 int i2d_ASN1_OBJECT(ASN1_OBJECT *a, unsigned char **pp)
        {
index a6acef1..36becea 100644 (file)
@@ -59,6 +59,7 @@
 #include <stdio.h>
 #include "cryptlib.h"
 #include <openssl/asn1t.h>
+#include <openssl/objects.h>
 
 int ASN1_TYPE_get(ASN1_TYPE *a)
        {
@@ -79,6 +80,31 @@ void ASN1_TYPE_set(ASN1_TYPE *a, int type, void *value)
        a->value.ptr=value;
        }
 
+int ASN1_TYPE_set1(ASN1_TYPE *a, int type, const void *value)
+       {
+       if (!value || (type == V_ASN1_BOOLEAN))
+               {
+               void *p = (void *)value;
+               ASN1_TYPE_set(a, type, p);
+               }
+       else if (type == V_ASN1_OBJECT)
+               {
+               ASN1_OBJECT *odup;
+               odup = OBJ_dup(value);
+               if (!odup)
+                       return 0;
+               ASN1_TYPE_set(a, type, odup);
+               }
+       else
+               {
+               ASN1_STRING *sdup;
+               sdup = ASN1_STRING_dup((ASN1_STRING *)value);
+               if (!sdup)
+                       return 0;
+               ASN1_TYPE_set(a, type, sdup);
+               }
+       return 1;
+       }
 
 IMPLEMENT_STACK_OF(ASN1_TYPE)
 IMPLEMENT_ASN1_SET_OF(ASN1_TYPE)
index f15131e..424cd34 100644 (file)
@@ -158,7 +158,12 @@ extern "C" {
 #define MBSTRING_BMP           (MBSTRING_FLAG|2)
 #define MBSTRING_UNIV          (MBSTRING_FLAG|4)
 
+#define SMIME_OLDMIME          0x400
+#define SMIME_CRLFEOL          0x800
+#define SMIME_STREAM           0x1000
+
 struct X509_algor_st;
+DECLARE_STACK_OF(X509_ALGOR)
 
 #define DECLARE_ASN1_SET_OF(type) /* filled in by mkstack.pl */
 #define IMPLEMENT_ASN1_SET_OF(type) /* nothing, no longer needed */
@@ -218,6 +223,13 @@ typedef struct asn1_object_st
  * be inserted in the memory buffer 
  */
 #define ASN1_STRING_FLAG_NDEF 0x010 
+
+/* This flag is used by the CMS code to indicate that a string is not
+ * complete and is a place holder for content when it had all been 
+ * accessed. The flag will be reset when content has been written to it.
+ */
+#define ASN1_STRING_FLAG_CONT 0x020 
+
 /* This is the base type that holds just about everything :-) */
 typedef struct asn1_string_st
        {
@@ -311,8 +323,8 @@ typedef struct ASN1_VALUE_st ASN1_VALUE;
        int i2d_##name##_NDEF(name *a, unsigned char **out);
 
 #define DECLARE_ASN1_FUNCTIONS_const(name) \
-       name *name##_new(void); \
-       void name##_free(name *a);
+       DECLARE_ASN1_ALLOC_FUNCTIONS(name) \
+       DECLARE_ASN1_ENCODE_FUNCTIONS_const(name, name)
 
 #define DECLARE_ASN1_ALLOC_FUNCTIONS_name(type, name) \
        type *name##_new(void); \
@@ -522,6 +534,7 @@ typedef struct asn1_type_st
                 * contain the set or sequence bytes */
                ASN1_STRING *           set;
                ASN1_STRING *           sequence;
+               ASN1_VALUE  *           asn1_value;
                } value;
        } ASN1_TYPE;
 
@@ -752,6 +765,7 @@ DECLARE_ASN1_FUNCTIONS_fname(ASN1_TYPE, ASN1_ANY, ASN1_TYPE)
 
 int ASN1_TYPE_get(ASN1_TYPE *a);
 void ASN1_TYPE_set(ASN1_TYPE *a, int type, void *value);
+int ASN1_TYPE_set1(ASN1_TYPE *a, int type, const void *value);
 
 ASN1_OBJECT *  ASN1_OBJECT_new(void );
 void           ASN1_OBJECT_free(ASN1_OBJECT *a);
@@ -774,6 +788,7 @@ int                 ASN1_STRING_cmp(ASN1_STRING *a, ASN1_STRING *b);
   /* Since this is used to store all sorts of things, via macros, for now, make
      its data void * */
 int            ASN1_STRING_set(ASN1_STRING *str, const void *data, int len);
+void           ASN1_STRING_set0(ASN1_STRING *str, void *data, int len);
 int ASN1_STRING_length(ASN1_STRING *x);
 void ASN1_STRING_length_set(ASN1_STRING *x, int n);
 int ASN1_STRING_type(ASN1_STRING *x);
@@ -926,6 +941,12 @@ void *ASN1_dup(i2d_of_void *i2d, d2i_of_void *d2i, char *x);
 
 void *ASN1_item_dup(const ASN1_ITEM *it, void *x);
 
+/* ASN1 alloc/free macros for when a type is only used internally */
+
+#define M_ASN1_new_of(type) (type *)ASN1_item_new(ASN1_ITEM_rptr(type))
+#define M_ASN1_free_of(x, type) \
+               ASN1_item_free(CHECKED_PTR_OF(type, x), ASN1_ITEM_rptr(type))
+
 #ifndef OPENSSL_NO_FP_API
 void *ASN1_d2i_fp(void *(*xnew)(void), d2i_of_void *d2i, FILE *in, void **x);
 
@@ -1054,7 +1075,17 @@ void ASN1_add_oid_module(void);
 
 ASN1_TYPE *ASN1_generate_nconf(char *str, CONF *nconf);
 ASN1_TYPE *ASN1_generate_v3(char *str, X509V3_CTX *cnf);
-       
+
+typedef int asn1_output_data_fn(BIO *out, BIO *data, ASN1_VALUE *val, int flags,
+                                       const ASN1_ITEM *it);
+
+int int_smime_write_ASN1(BIO *bio, ASN1_VALUE *val, BIO *data, int flags,
+                               int ctype_nid, int econt_nid,
+                               STACK_OF(X509_ALGOR) *mdalgs,
+                               asn1_output_data_fn *data_fn,
+                               const ASN1_ITEM *it);
+ASN1_VALUE *SMIME_read_ASN1(BIO *bio, BIO **bcont, const ASN1_ITEM *it);
+
 /* BEGIN ERROR CODES */
 /* The following lines are auto generated by the script mkerr.pl. Any changes
  * made after this point may be overwritten when the script is next run.
@@ -1104,6 +1135,7 @@ void ERR_load_ASN1_strings(void);
 #define ASN1_F_ASN1_ITEM_VERIFY                                 197
 #define ASN1_F_ASN1_MBSTRING_NCOPY                      122
 #define ASN1_F_ASN1_OBJECT_NEW                          123
+#define ASN1_F_ASN1_OUTPUT_DATA                                 207
 #define ASN1_F_ASN1_PACK_STRING                                 124
 #define ASN1_F_ASN1_PCTX_NEW                            205
 #define ASN1_F_ASN1_PKCS5_PBE_SET                       125
@@ -1123,6 +1155,8 @@ void ERR_load_ASN1_strings(void);
 #define ASN1_F_ASN1_UNPACK_STRING                       136
 #define ASN1_F_ASN1_UTCTIME_SET                                 187
 #define ASN1_F_ASN1_VERIFY                              137
+#define ASN1_F_B64_READ_ASN1                            208
+#define ASN1_F_B64_WRITE_ASN1                           209
 #define ASN1_F_BITSTR_CB                                180
 #define ASN1_F_BN_TO_ASN1_ENUMERATED                    138
 #define ASN1_F_BN_TO_ASN1_INTEGER                       139
@@ -1163,6 +1197,8 @@ void ERR_load_ASN1_strings(void);
 #define ASN1_F_PARSE_TAGGING                            182
 #define ASN1_F_PKCS5_PBE2_SET                           167
 #define ASN1_F_PKCS5_PBE_SET                            202
+#define ASN1_F_SMIME_READ_ASN1                          210
+#define ASN1_F_SMIME_TEXT                               211
 #define ASN1_F_X509_CINF_NEW                            168
 #define ASN1_F_X509_CRL_ADD0_REVOKED                    169
 #define ASN1_F_X509_INFO_NEW                            170
@@ -1174,6 +1210,8 @@ void ERR_load_ASN1_strings(void);
 
 /* Reason codes. */
 #define ASN1_R_ADDING_OBJECT                            171
+#define ASN1_R_ASN1_PARSE_ERROR                                 198
+#define ASN1_R_ASN1_SIG_PARSE_ERROR                     199
 #define ASN1_R_AUX_ERROR                                100
 #define ASN1_R_BAD_CLASS                                101
 #define ASN1_R_BAD_OBJECT_HEADER                        102
@@ -1220,6 +1258,7 @@ void ERR_load_ASN1_strings(void);
 #define ASN1_R_INTEGER_TOO_LARGE_FOR_LONG               128
 #define ASN1_R_INVALID_BMPSTRING_LENGTH                         129
 #define ASN1_R_INVALID_DIGIT                            130
+#define ASN1_R_INVALID_MIME_TYPE                        200
 #define ASN1_R_INVALID_MODIFIER                                 186
 #define ASN1_R_INVALID_NUMBER                           187
 #define ASN1_R_INVALID_SEPARATOR                        131
@@ -1229,6 +1268,9 @@ void ERR_load_ASN1_strings(void);
 #define ASN1_R_IV_TOO_LARGE                             135
 #define ASN1_R_LENGTH_ERROR                             136
 #define ASN1_R_LIST_ERROR                               188
+#define ASN1_R_MIME_NO_CONTENT_TYPE                     201
+#define ASN1_R_MIME_PARSE_ERROR                                 202
+#define ASN1_R_MIME_SIG_PARSE_ERROR                     203
 #define ASN1_R_MISSING_EOC                              137
 #define ASN1_R_MISSING_SECOND_NUMBER                    138
 #define ASN1_R_MISSING_VALUE                            189
@@ -1238,7 +1280,11 @@ void ERR_load_ASN1_strings(void);
 #define ASN1_R_NON_HEX_CHARACTERS                       141
 #define ASN1_R_NOT_ASCII_FORMAT                                 190
 #define ASN1_R_NOT_ENOUGH_DATA                          142
+#define ASN1_R_NO_CONTENT_TYPE                          204
 #define ASN1_R_NO_MATCHING_CHOICE_TYPE                  143
+#define ASN1_R_NO_MULTIPART_BODY_FAILURE                205
+#define ASN1_R_NO_MULTIPART_BOUNDARY                    206
+#define ASN1_R_NO_SIG_CONTENT_TYPE                      207
 #define ASN1_R_NULL_IS_WRONG_LENGTH                     144
 #define ASN1_R_OBJECT_NOT_ASCII_FORMAT                  191
 #define ASN1_R_ODD_NUMBER_OF_CHARS                      145
@@ -1248,6 +1294,8 @@ void ERR_load_ASN1_strings(void);
 #define ASN1_R_SEQUENCE_NOT_CONSTRUCTED                         149
 #define ASN1_R_SEQUENCE_OR_SET_NEEDS_CONFIG             192
 #define ASN1_R_SHORT_LINE                               150
+#define ASN1_R_SIG_INVALID_MIME_TYPE                    208
+#define ASN1_R_STREAMING_NOT_SUPPORTED                  209
 #define ASN1_R_STRING_TOO_LONG                          151
 #define ASN1_R_STRING_TOO_SHORT                                 152
 #define ASN1_R_TAG_VALUE_TOO_HIGH                       153
index f6b5c3f..f8a3e2e 100644 (file)
@@ -1,6 +1,6 @@
 /* crypto/asn1/asn1_err.c */
 /* ====================================================================
- * Copyright (c) 1999-2005 The OpenSSL Project.  All rights reserved.
+ * Copyright (c) 1999-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
@@ -110,6 +110,7 @@ static ERR_STRING_DATA ASN1_str_functs[]=
 {ERR_FUNC(ASN1_F_ASN1_ITEM_VERIFY),    "ASN1_item_verify"},
 {ERR_FUNC(ASN1_F_ASN1_MBSTRING_NCOPY), "ASN1_mbstring_ncopy"},
 {ERR_FUNC(ASN1_F_ASN1_OBJECT_NEW),     "ASN1_OBJECT_new"},
+{ERR_FUNC(ASN1_F_ASN1_OUTPUT_DATA),    "ASN1_OUTPUT_DATA"},
 {ERR_FUNC(ASN1_F_ASN1_PACK_STRING),    "ASN1_pack_string"},
 {ERR_FUNC(ASN1_F_ASN1_PCTX_NEW),       "ASN1_PCTX_NEW"},
 {ERR_FUNC(ASN1_F_ASN1_PKCS5_PBE_SET),  "ASN1_PKCS5_PBE_SET"},
@@ -129,6 +130,8 @@ static ERR_STRING_DATA ASN1_str_functs[]=
 {ERR_FUNC(ASN1_F_ASN1_UNPACK_STRING),  "ASN1_unpack_string"},
 {ERR_FUNC(ASN1_F_ASN1_UTCTIME_SET),    "ASN1_UTCTIME_set"},
 {ERR_FUNC(ASN1_F_ASN1_VERIFY), "ASN1_verify"},
+{ERR_FUNC(ASN1_F_B64_READ_ASN1),       "B64_READ_ASN1"},
+{ERR_FUNC(ASN1_F_B64_WRITE_ASN1),      "B64_WRITE_ASN1"},
 {ERR_FUNC(ASN1_F_BITSTR_CB),   "BITSTR_CB"},
 {ERR_FUNC(ASN1_F_BN_TO_ASN1_ENUMERATED),       "BN_to_ASN1_ENUMERATED"},
 {ERR_FUNC(ASN1_F_BN_TO_ASN1_INTEGER),  "BN_to_ASN1_INTEGER"},
@@ -169,6 +172,8 @@ static ERR_STRING_DATA ASN1_str_functs[]=
 {ERR_FUNC(ASN1_F_PARSE_TAGGING),       "PARSE_TAGGING"},
 {ERR_FUNC(ASN1_F_PKCS5_PBE2_SET),      "PKCS5_pbe2_set"},
 {ERR_FUNC(ASN1_F_PKCS5_PBE_SET),       "PKCS5_pbe_set"},
+{ERR_FUNC(ASN1_F_SMIME_READ_ASN1),     "SMIME_read_ASN1"},
+{ERR_FUNC(ASN1_F_SMIME_TEXT),  "SMIME_text"},
 {ERR_FUNC(ASN1_F_X509_CINF_NEW),       "X509_CINF_NEW"},
 {ERR_FUNC(ASN1_F_X509_CRL_ADD0_REVOKED),       "X509_CRL_add0_revoked"},
 {ERR_FUNC(ASN1_F_X509_INFO_NEW),       "X509_INFO_new"},
@@ -183,6 +188,8 @@ static ERR_STRING_DATA ASN1_str_functs[]=
 static ERR_STRING_DATA ASN1_str_reasons[]=
        {
 {ERR_REASON(ASN1_R_ADDING_OBJECT)        ,"adding object"},
+{ERR_REASON(ASN1_R_ASN1_PARSE_ERROR)     ,"asn1 parse error"},
+{ERR_REASON(ASN1_R_ASN1_SIG_PARSE_ERROR) ,"asn1 sig parse error"},
 {ERR_REASON(ASN1_R_AUX_ERROR)            ,"aux error"},
 {ERR_REASON(ASN1_R_BAD_CLASS)            ,"bad class"},
 {ERR_REASON(ASN1_R_BAD_OBJECT_HEADER)    ,"bad object header"},
@@ -229,6 +236,7 @@ static ERR_STRING_DATA ASN1_str_reasons[]=
 {ERR_REASON(ASN1_R_INTEGER_TOO_LARGE_FOR_LONG),"integer too large for long"},
 {ERR_REASON(ASN1_R_INVALID_BMPSTRING_LENGTH),"invalid bmpstring length"},
 {ERR_REASON(ASN1_R_INVALID_DIGIT)        ,"invalid digit"},
+{ERR_REASON(ASN1_R_INVALID_MIME_TYPE)    ,"invalid mime type"},
 {ERR_REASON(ASN1_R_INVALID_MODIFIER)     ,"invalid modifier"},
 {ERR_REASON(ASN1_R_INVALID_NUMBER)       ,"invalid number"},
 {ERR_REASON(ASN1_R_INVALID_SEPARATOR)    ,"invalid separator"},
@@ -238,6 +246,9 @@ static ERR_STRING_DATA ASN1_str_reasons[]=
 {ERR_REASON(ASN1_R_IV_TOO_LARGE)         ,"iv too large"},
 {ERR_REASON(ASN1_R_LENGTH_ERROR)         ,"length error"},
 {ERR_REASON(ASN1_R_LIST_ERROR)           ,"list error"},
+{ERR_REASON(ASN1_R_MIME_NO_CONTENT_TYPE) ,"mime no content type"},
+{ERR_REASON(ASN1_R_MIME_PARSE_ERROR)     ,"mime parse error"},
+{ERR_REASON(ASN1_R_MIME_SIG_PARSE_ERROR) ,"mime sig parse error"},
 {ERR_REASON(ASN1_R_MISSING_EOC)          ,"missing eoc"},
 {ERR_REASON(ASN1_R_MISSING_SECOND_NUMBER),"missing second number"},
 {ERR_REASON(ASN1_R_MISSING_VALUE)        ,"missing value"},
@@ -247,7 +258,11 @@ static ERR_STRING_DATA ASN1_str_reasons[]=
 {ERR_REASON(ASN1_R_NON_HEX_CHARACTERS)   ,"non hex characters"},
 {ERR_REASON(ASN1_R_NOT_ASCII_FORMAT)     ,"not ascii format"},
 {ERR_REASON(ASN1_R_NOT_ENOUGH_DATA)      ,"not enough data"},
+{ERR_REASON(ASN1_R_NO_CONTENT_TYPE)      ,"no content type"},
 {ERR_REASON(ASN1_R_NO_MATCHING_CHOICE_TYPE),"no matching choice type"},
+{ERR_REASON(ASN1_R_NO_MULTIPART_BODY_FAILURE),"no multipart body failure"},
+{ERR_REASON(ASN1_R_NO_MULTIPART_BOUNDARY),"no multipart boundary"},
+{ERR_REASON(ASN1_R_NO_SIG_CONTENT_TYPE)  ,"no sig content type"},
 {ERR_REASON(ASN1_R_NULL_IS_WRONG_LENGTH) ,"null is wrong length"},
 {ERR_REASON(ASN1_R_OBJECT_NOT_ASCII_FORMAT),"object not ascii format"},
 {ERR_REASON(ASN1_R_ODD_NUMBER_OF_CHARS)  ,"odd number of chars"},
@@ -257,6 +272,8 @@ static ERR_STRING_DATA ASN1_str_reasons[]=
 {ERR_REASON(ASN1_R_SEQUENCE_NOT_CONSTRUCTED),"sequence not constructed"},
 {ERR_REASON(ASN1_R_SEQUENCE_OR_SET_NEEDS_CONFIG),"sequence or set needs config"},
 {ERR_REASON(ASN1_R_SHORT_LINE)           ,"short line"},
+{ERR_REASON(ASN1_R_SIG_INVALID_MIME_TYPE),"sig invalid mime type"},
+{ERR_REASON(ASN1_R_STREAMING_NOT_SUPPORTED),"streaming not supported"},
 {ERR_REASON(ASN1_R_STRING_TOO_LONG)      ,"string too long"},
 {ERR_REASON(ASN1_R_STRING_TOO_SHORT)     ,"string too short"},
 {ERR_REASON(ASN1_R_TAG_VALUE_TOO_HIGH)   ,"tag value too high"},
index d5ae5b2..5af559e 100644 (file)
@@ -393,6 +393,14 @@ int ASN1_STRING_set(ASN1_STRING *str, const void *_data, int len)
        return(1);
        }
 
+void ASN1_STRING_set0(ASN1_STRING *str, void *data, int len)
+       {
+       if (str->data)
+               OPENSSL_free(str->data);
+       str->data = data;
+       str->length = len;
+       }
+
 ASN1_STRING *ASN1_STRING_new(void)
        {
        return(ASN1_STRING_type_new(V_ASN1_OCTET_STRING));
index adbc2a6..bf315e6 100644 (file)
@@ -169,6 +169,9 @@ extern "C" {
 #define ASN1_NDEF_SEQUENCE(tname) \
        ASN1_SEQUENCE(tname)
 
+#define ASN1_NDEF_SEQUENCE_cb(tname, cb) \
+       ASN1_SEQUENCE_cb(tname, cb)
+
 #define ASN1_SEQUENCE_cb(tname, cb) \
        static const ASN1_AUX tname##_aux = {NULL, 0, 0, 0, cb, 0}; \
        ASN1_SEQUENCE(tname)
@@ -368,6 +371,10 @@ extern "C" {
 #define ASN1_EXP_SEQUENCE_OF_OPT(stname, field, type, tag) \
                        ASN1_EXP_EX(stname, field, type, tag, ASN1_TFLG_SEQUENCE_OF|ASN1_TFLG_OPTIONAL)
 
+/* EXPLICIT using indefinite length constructed form */
+#define ASN1_NDEF_EXP(stname, field, type, tag) \
+                       ASN1_EXP_EX(stname, field, type, tag, ASN1_TFLG_NDEF)
+
 /* EXPLICIT OPTIONAL using indefinite length constructed form */
 #define ASN1_NDEF_EXP_OPT(stname, field, type, tag) \
                        ASN1_EXP_EX(stname, field, type, tag, ASN1_TFLG_OPTIONAL|ASN1_TFLG_NDEF)
similarity index 75%
copy from crypto/openssl-0.9/crypto/pkcs7/pk7_mime.c
copy to crypto/openssl-0.9/crypto/asn1/asn_mime.c
index 25566a4..fe7c4ec 100644 (file)
@@ -1,9 +1,9 @@
-/* pk7_mime.c */
-/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
+/* asn_mime.c */
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
  * project.
  */
 /* ====================================================================
- * Copyright (c) 1999-2005 The OpenSSL Project.  All rights reserved.
+ * Copyright (c) 1999-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
  * OF THE POSSIBILITY OF SUCH DAMAGE.
  * ====================================================================
  *
- * This product includes cryptographic software written by Eric Young
- * (eay@cryptsoft.com).  This product includes software written by Tim
- * Hudson (tjh@cryptsoft.com).
- *
  */
 
 #include <stdio.h>
 #include "cryptlib.h"
 #include <openssl/rand.h>
 #include <openssl/x509.h>
+#include <openssl/asn1.h>
+#include <openssl/asn1t.h>
 
-/* MIME and related routines */
+/* Generalised MIME like utilities for streaming ASN1. Although many
+ * have a PKCS7/CMS like flavour others are more general purpose.
+ */
 
 /* MIME format structures
  * Note that all are translated to lower case apart from
@@ -86,9 +86,6 @@ STACK_OF(MIME_PARAM) *params;         /* Zero or more parameters */
 DECLARE_STACK_OF(MIME_HEADER)
 IMPLEMENT_STACK_OF(MIME_HEADER)
 
-static int pkcs7_output_data(BIO *bio, BIO *data, PKCS7 *p7, int flags);
-static int B64_write_PKCS7(BIO *bio, PKCS7 *p7);
-static PKCS7 *B64_read_PKCS7(BIO *bio);
 static char * strip_ends(char *name);
 static char * strip_start(char *name);
 static char * strip_end(char *name);
@@ -110,57 +107,123 @@ static void mime_hdr_free(MIME_HEADER *hdr);
 #define MAX_SMLEN 1024
 #define mime_debug(x) /* x */
 
-/* Base 64 read and write of PKCS#7 structure */
+/* Base 64 read and write of ASN1 structure */
 
-static int B64_write_PKCS7(BIO *bio, PKCS7 *p7)
-{
+static int B64_write_ASN1(BIO *out, ASN1_VALUE *val, BIO *in, int flags,
+                               const ASN1_ITEM *it)
+       {
        BIO *b64;
-       if(!(b64 = BIO_new(BIO_f_base64()))) {
-               PKCS7err(PKCS7_F_B64_WRITE_PKCS7,ERR_R_MALLOC_FAILURE);
+       int r;
+       b64 = BIO_new(BIO_f_base64());
+       if(!b64)
+               {
+               ASN1err(ASN1_F_B64_WRITE_ASN1,ERR_R_MALLOC_FAILURE);
                return 0;
-       }
-       bio = BIO_push(b64, bio);
-       i2d_PKCS7_bio(bio, p7);
-       (void)BIO_flush(bio);
-       bio = BIO_pop(bio);
+               }
+       /* prepend the b64 BIO so all data is base64 encoded.
+        */
+       out = BIO_push(b64, out);
+       r = ASN1_item_i2d_bio(it, out, val);
+       (void)BIO_flush(out);
+       BIO_pop(out);
        BIO_free(b64);
-       return 1;
-}
+       return r;
+       }
 
-static PKCS7 *B64_read_PKCS7(BIO *bio)
+static ASN1_VALUE *b64_read_asn1(BIO *bio, const ASN1_ITEM *it)
 {
        BIO *b64;
-       PKCS7 *p7;
+       ASN1_VALUE *val;
        if(!(b64 = BIO_new(BIO_f_base64()))) {
-               PKCS7err(PKCS7_F_B64_READ_PKCS7,ERR_R_MALLOC_FAILURE);
+               ASN1err(ASN1_F_B64_READ_ASN1,ERR_R_MALLOC_FAILURE);
                return 0;
        }
        bio = BIO_push(b64, bio);
-       if(!(p7 = d2i_PKCS7_bio(bio, NULL))) 
-               PKCS7err(PKCS7_F_B64_READ_PKCS7,PKCS7_R_DECODE_ERROR);
+       val = ASN1_item_d2i_bio(it, bio, NULL);
+       if(!val)
+               ASN1err(ASN1_F_B64_READ_ASN1,ASN1_R_DECODE_ERROR);
        (void)BIO_flush(bio);
        bio = BIO_pop(bio);
        BIO_free(b64);
-       return p7;
+       return val;
 }
 
+/* Generate the MIME "micalg" parameter from RFC3851, RFC4490 */
+
+static int asn1_write_micalg(BIO *out, STACK_OF(X509_ALGOR) *mdalgs)
+       {
+       const EVP_MD *md;
+       int i, have_unknown = 0, write_comma, md_nid;
+       have_unknown = 0;
+       write_comma = 0;
+       for (i = 0; i < sk_X509_ALGOR_num(mdalgs); i++)
+               {
+               if (write_comma)
+                       BIO_write(out, ",", 1);
+               write_comma = 1;
+               md_nid = OBJ_obj2nid(sk_X509_ALGOR_value(mdalgs, i)->algorithm);
+               md = EVP_get_digestbynid(md_nid);
+               switch(md_nid)
+                       {
+                       case NID_sha1:
+                       BIO_puts(out, "sha1");
+                       break;
+
+                       case NID_md5:
+                       BIO_puts(out, "md5");
+                       break;
+
+                       case NID_sha256:
+                       BIO_puts(out, "sha-256");
+                       break;
+
+                       case NID_sha384:
+                       BIO_puts(out, "sha-384");
+                       break;
+
+                       case NID_sha512:
+                       BIO_puts(out, "sha-512");
+                       break;
+
+                       default:
+                       if (have_unknown)
+                               write_comma = 0;
+                       else
+                               {
+                               BIO_puts(out, "unknown");
+                               have_unknown = 1;
+                               }
+                       break;
+
+                       }
+               }
+
+       return 1;
+
+       }
+
 /* SMIME sender */
 
-int SMIME_write_PKCS7(BIO *bio, PKCS7 *p7, BIO *data, int flags)
+int int_smime_write_ASN1(BIO *bio, ASN1_VALUE *val, BIO *data, int flags,
+                               int ctype_nid, int econt_nid,
+                               STACK_OF(X509_ALGOR) *mdalgs,
+                               asn1_output_data_fn *data_fn,
+                               const ASN1_ITEM *it)
 {
        char bound[33], c;
        int i;
-       char *mime_prefix, *mime_eol, *msg_type=NULL;
-       if (flags & PKCS7_NOOLDMIMETYPE)
-               mime_prefix = "application/pkcs7-";
-       else
+       const char *mime_prefix, *mime_eol, *cname = "smime.p7m";
+       const char *msg_type=NULL;
+       if (flags & SMIME_OLDMIME)
                mime_prefix = "application/x-pkcs7-";
+       else
+               mime_prefix = "application/pkcs7-";
 
-       if (flags & PKCS7_CRLFEOL)
+       if (flags & SMIME_CRLFEOL)
                mime_eol = "\r\n";
        else
                mime_eol = "\n";
-       if((flags & PKCS7_DETACHED) && data) {
+       if((flags & SMIME_DETACHED) && data) {
        /* We want multipart/signed */
                /* Generate a random boundary */
                RAND_pseudo_bytes((unsigned char *)bound, 32);
@@ -174,13 +237,16 @@ int SMIME_write_PKCS7(BIO *bio, PKCS7 *p7, BIO *data, int flags)
                BIO_printf(bio, "MIME-Version: 1.0%s", mime_eol);
                BIO_printf(bio, "Content-Type: multipart/signed;");
                BIO_printf(bio, " protocol=\"%ssignature\";", mime_prefix);
-               BIO_printf(bio, " micalg=sha1; boundary=\"----%s\"%s%s",
+               BIO_puts(bio, " micalg=\"");
+               asn1_write_micalg(bio, mdalgs);
+               BIO_printf(bio, "\"; boundary=\"----%s\"%s%s",
                                                bound, mime_eol, mime_eol);
                BIO_printf(bio, "This is an S/MIME signed message%s%s",
                                                mime_eol, mime_eol);
                /* Now write out the first part */
                BIO_printf(bio, "------%s%s", bound, mime_eol);
-               pkcs7_output_data(bio, data, p7, flags);
+               if (!data_fn(bio, data, val, flags, it))
+                       return 0;
                BIO_printf(bio, "%s------%s%s", mime_eol, bound, mime_eol);
 
                /* Headers for signature */
@@ -192,7 +258,7 @@ int SMIME_write_PKCS7(BIO *bio, PKCS7 *p7, BIO *data, int flags)
                BIO_printf(bio, "Content-Disposition: attachment;");
                BIO_printf(bio, " filename=\"smime.p7s\"%s%s",
                                                        mime_eol, mime_eol);
-               B64_write_PKCS7(bio, p7);
+               B64_write_ASN1(bio, val, NULL, 0, it);
                BIO_printf(bio,"%s------%s--%s%s", mime_eol, bound,
                                                        mime_eol, mime_eol);
                return 1;
@@ -200,100 +266,119 @@ int SMIME_write_PKCS7(BIO *bio, PKCS7 *p7, BIO *data, int flags)
 
        /* Determine smime-type header */
 
-       if (PKCS7_type_is_enveloped(p7))
+       if (ctype_nid == NID_pkcs7_enveloped)
                msg_type = "enveloped-data";
-       else if (PKCS7_type_is_signed(p7))
+       else if (ctype_nid == NID_pkcs7_signed)
                {
-               /* If we have any signers it is signed-data othewise 
-                * certs-only.
-                */
-               STACK_OF(PKCS7_SIGNER_INFO) *sinfos;
-               sinfos = PKCS7_get_signer_info(p7);
-               if (sk_PKCS7_SIGNER_INFO_num(sinfos) > 0)
+               if (econt_nid == NID_id_smime_ct_receipt)
+                       msg_type = "signed-receipt";
+               else if (sk_X509_ALGOR_num(mdalgs) >= 0)
                        msg_type = "signed-data";
                else
                        msg_type = "certs-only";
                }
+       else if (ctype_nid == NID_id_smime_ct_compressedData)
+               {
+               msg_type = "compressed-data";
+               cname = "smime.p7z";
+               }
        /* MIME headers */
        BIO_printf(bio, "MIME-Version: 1.0%s", mime_eol);
        BIO_printf(bio, "Content-Disposition: attachment;");
-       BIO_printf(bio, " filename=\"smime.p7m\"%s", mime_eol);
+       BIO_printf(bio, " filename=\"%s\"%s", cname, mime_eol);
        BIO_printf(bio, "Content-Type: %smime;", mime_prefix);
        if (msg_type)
                BIO_printf(bio, " smime-type=%s;", msg_type);
-       BIO_printf(bio, " name=\"smime.p7m\"%s", mime_eol);
+       BIO_printf(bio, " name=\"%s\"%s", cname, mime_eol);
        BIO_printf(bio, "Content-Transfer-Encoding: base64%s%s",
                                                mime_eol, mime_eol);
-       B64_write_PKCS7(bio, p7);
+       if (!B64_write_ASN1(bio, val, data, flags, it))
+               return 0;
        BIO_printf(bio, "%s", mime_eol);
        return 1;
 }
 
-/* Handle output of PKCS#7 data */
+#if 0
 
+/* Handle output of ASN1 data */
 
-static int pkcs7_output_data(BIO *out, BIO *data, PKCS7 *p7, int flags)
+
+static int asn1_output_data(BIO *out, BIO *data, ASN1_VALUE *val, int flags,
+                                       const ASN1_ITEM *it)
        {
-       BIO *tmpbio, *p7bio;
+       BIO *tmpbio;
+       const ASN1_AUX *aux = it->funcs;
+       ASN1_STREAM_ARG sarg;
 
-       if (!(flags & PKCS7_STREAM))
+       if (!(flags & SMIME_DETACHED))
                {
                SMIME_crlf_copy(data, out, flags);
                return 1;
                }
 
-       /* Partial sign operation */
+       if (!aux || !aux->asn1_cb)
+               {
+               ASN1err(ASN1_F_ASN1_OUTPUT_DATA,
+                                       ASN1_R_STREAMING_NOT_SUPPORTED);
+               return 0;
+               }
 
-       /* Initialize sign operation */
-       p7bio = PKCS7_dataInit(p7, out);
+       sarg.out = out;
+       sarg.ndef_bio = NULL;
+       sarg.boundary = NULL;
 
-       /* Copy data across, computing digests etc */
-       SMIME_crlf_copy(data, p7bio, flags);
+       /* Let ASN1 code prepend any needed BIOs */
 
-       /* Must be detached */
-       PKCS7_set_detached(p7, 1);
+       if (aux->asn1_cb(ASN1_OP_DETACHED_PRE, &val, it, &sarg) <= 0)
+               return 0;
+
+       /* Copy data across, passing through filter BIOs for processing */
+       SMIME_crlf_copy(data, sarg.ndef_bio, flags);
 
-       /* Finalize signatures */
-       PKCS7_dataFinal(p7, p7bio);
+       /* Finalize structure */
+       if (aux->asn1_cb(ASN1_OP_DETACHED_POST, &val, it, &sarg) <= 0)
+               return 0;
 
        /* Now remove any digests prepended to the BIO */
 
-       while (p7bio != out)
+       while (sarg.ndef_bio != out)
                {
-               tmpbio = BIO_pop(p7bio);
-               BIO_free(p7bio);
-               p7bio = tmpbio;
+               tmpbio = BIO_pop(sarg.ndef_bio);
+               BIO_free(sarg.ndef_bio);
+               sarg.ndef_bio = tmpbio;
                }
 
        return 1;
 
        }
 
+#endif
+
 /* SMIME reader: handle multipart/signed and opaque signing.
  * in multipart case the content is placed in a memory BIO
  * pointed to by "bcont". In opaque this is set to NULL
  */
 
-PKCS7 *SMIME_read_PKCS7(BIO *bio, BIO **bcont)
+ASN1_VALUE *SMIME_read_ASN1(BIO *bio, BIO **bcont, const ASN1_ITEM *it)
 {
-       BIO *p7in;
+       BIO *asnin;
        STACK_OF(MIME_HEADER) *headers = NULL;
        STACK_OF(BIO) *parts = NULL;
        MIME_HEADER *hdr;
        MIME_PARAM *prm;
-       PKCS7 *p7;
+       ASN1_VALUE *val;
        int ret;
 
        if(bcont) *bcont = NULL;
 
        if (!(headers = mime_parse_hdr(bio))) {
-               PKCS7err(PKCS7_F_SMIME_READ_PKCS7,PKCS7_R_MIME_PARSE_ERROR);
+               ASN1err(ASN1_F_SMIME_READ_ASN1,ASN1_R_MIME_PARSE_ERROR);
                return NULL;
        }
 
        if(!(hdr = mime_hdr_find(headers, "content-type")) || !hdr->value) {
                sk_MIME_HEADER_pop_free(headers, mime_hdr_free);
-               PKCS7err(PKCS7_F_SMIME_READ_PKCS7, PKCS7_R_NO_CONTENT_TYPE);
+               ASN1err(ASN1_F_SMIME_READ_ASN1, ASN1_R_NO_CONTENT_TYPE);
                return NULL;
        }
 
@@ -304,22 +389,22 @@ PKCS7 *SMIME_read_PKCS7(BIO *bio, BIO **bcont)
                prm = mime_param_find(hdr, "boundary");
                if(!prm || !prm->param_value) {
                        sk_MIME_HEADER_pop_free(headers, mime_hdr_free);
-                       PKCS7err(PKCS7_F_SMIME_READ_PKCS7, PKCS7_R_NO_MULTIPART_BOUNDARY);
+                       ASN1err(ASN1_F_SMIME_READ_ASN1, ASN1_R_NO_MULTIPART_BOUNDARY);
                        return NULL;
                }
                ret = multi_split(bio, prm->param_value, &parts);
                sk_MIME_HEADER_pop_free(headers, mime_hdr_free);
                if(!ret || (sk_BIO_num(parts) != 2) ) {
-                       PKCS7err(PKCS7_F_SMIME_READ_PKCS7, PKCS7_R_NO_MULTIPART_BODY_FAILURE);
+                       ASN1err(ASN1_F_SMIME_READ_ASN1, ASN1_R_NO_MULTIPART_BODY_FAILURE);
                        sk_BIO_pop_free(parts, BIO_vfree);
                        return NULL;
                }
 
                /* Parse the signature piece */
-               p7in = sk_BIO_value(parts, 1);
+               asnin = sk_BIO_value(parts, 1);
 
-               if (!(headers = mime_parse_hdr(p7in))) {
-                       PKCS7err(PKCS7_F_SMIME_READ_PKCS7,PKCS7_R_MIME_SIG_PARSE_ERROR);
+               if (!(headers = mime_parse_hdr(asnin))) {
+                       ASN1err(ASN1_F_SMIME_READ_ASN1,ASN1_R_MIME_SIG_PARSE_ERROR);
                        sk_BIO_pop_free(parts, BIO_vfree);
                        return NULL;
                }
@@ -329,39 +414,39 @@ PKCS7 *SMIME_read_PKCS7(BIO *bio, BIO **bcont)
                if(!(hdr = mime_hdr_find(headers, "content-type")) ||
                                                                 !hdr->value) {
                        sk_MIME_HEADER_pop_free(headers, mime_hdr_free);
-                       PKCS7err(PKCS7_F_SMIME_READ_PKCS7, PKCS7_R_NO_SIG_CONTENT_TYPE);
+                       ASN1err(ASN1_F_SMIME_READ_ASN1, ASN1_R_NO_SIG_CONTENT_TYPE);
                        return NULL;
                }
 
                if(strcmp(hdr->value, "application/x-pkcs7-signature") &&
                        strcmp(hdr->value, "application/pkcs7-signature")) {
                        sk_MIME_HEADER_pop_free(headers, mime_hdr_free);
-                       PKCS7err(PKCS7_F_SMIME_READ_PKCS7,PKCS7_R_SIG_INVALID_MIME_TYPE);
+                       ASN1err(ASN1_F_SMIME_READ_ASN1,ASN1_R_SIG_INVALID_MIME_TYPE);
                        ERR_add_error_data(2, "type: ", hdr->value);
                        sk_BIO_pop_free(parts, BIO_vfree);
                        return NULL;
                }
                sk_MIME_HEADER_pop_free(headers, mime_hdr_free);
-               /* Read in PKCS#7 */
-               if(!(p7 = B64_read_PKCS7(p7in))) {
-                       PKCS7err(PKCS7_F_SMIME_READ_PKCS7,PKCS7_R_PKCS7_SIG_PARSE_ERROR);
+               /* Read in ASN1 */
+               if(!(val = b64_read_asn1(asnin, it))) {
+                       ASN1err(ASN1_F_SMIME_READ_ASN1,ASN1_R_ASN1_SIG_PARSE_ERROR);
                        sk_BIO_pop_free(parts, BIO_vfree);
                        return NULL;
                }
 
                if(bcont) {
                        *bcont = sk_BIO_value(parts, 0);
-                       BIO_free(p7in);
+                       BIO_free(asnin);
                        sk_BIO_free(parts);
                } else sk_BIO_pop_free(parts, BIO_vfree);
-               return p7;
+               return val;
        }
                
        /* OK, if not multipart/signed try opaque signature */
 
        if (strcmp (hdr->value, "application/x-pkcs7-mime") &&
            strcmp (hdr->value, "application/pkcs7-mime")) {
-               PKCS7err(PKCS7_F_SMIME_READ_PKCS7,PKCS7_R_INVALID_MIME_TYPE);
+               ASN1err(ASN1_F_SMIME_READ_ASN1,ASN1_R_INVALID_MIME_TYPE);
                ERR_add_error_data(2, "type: ", hdr->value);
                sk_MIME_HEADER_pop_free(headers, mime_hdr_free);
                return NULL;
@@ -369,33 +454,49 @@ PKCS7 *SMIME_read_PKCS7(BIO *bio, BIO **bcont)
 
        sk_MIME_HEADER_pop_free(headers, mime_hdr_free);
        
-       if(!(p7 = B64_read_PKCS7(bio))) {
-               PKCS7err(PKCS7_F_SMIME_READ_PKCS7, PKCS7_R_PKCS7_PARSE_ERROR);
+       if(!(val = b64_read_asn1(bio, it))) {
+               ASN1err(ASN1_F_SMIME_READ_ASN1, ASN1_R_ASN1_PARSE_ERROR);
                return NULL;
        }
-       return p7;
+       return val;
 
 }
 
 /* Copy text from one BIO to another making the output CRLF at EOL */
 int SMIME_crlf_copy(BIO *in, BIO *out, int flags)
 {
+       BIO *bf;
        char eol;
        int len;
        char linebuf[MAX_SMLEN];
-       if(flags & PKCS7_BINARY) {
+       /* Buffer output so we don't write one line at a time. This is
+        * useful when streaming as we don't end up with one OCTET STRING
+        * per line.
+        */
+       bf = BIO_new(BIO_f_buffer());
+       if (!bf)
+               return 0;
+       out = BIO_push(bf, out);
+       if(flags & SMIME_BINARY)
+               {
                while((len = BIO_read(in, linebuf, MAX_SMLEN)) > 0)
                                                BIO_write(out, linebuf, len);
-               return 1;
-       }
-       if(flags & PKCS7_TEXT)
-               BIO_printf(out, "Content-Type: text/plain\r\n\r\n");
-       while ((len = BIO_gets(in, linebuf, MAX_SMLEN)) > 0) {
-               eol = strip_eol(linebuf, &len);
-               if (len)
-                       BIO_write(out, linebuf, len);
-               if(eol) BIO_write(out, "\r\n", 2);
-       }
+               }
+       else
+               {
+               if(flags & SMIME_TEXT)
+                       BIO_printf(out, "Content-Type: text/plain\r\n\r\n");
+               while ((len = BIO_gets(in, linebuf, MAX_SMLEN)) > 0)
+                       {
+                       eol = strip_eol(linebuf, &len);
+                       if (len)
+                               BIO_write(out, linebuf, len);
+                       if(eol) BIO_write(out, "\r\n", 2);
+                       }
+               }
+       (void)BIO_flush(out);
+       BIO_pop(out);
+       BIO_free(bf);
        return 1;
 }
 
@@ -408,16 +509,16 @@ int SMIME_text(BIO *in, BIO *out)
        MIME_HEADER *hdr;
 
        if (!(headers = mime_parse_hdr(in))) {
-               PKCS7err(PKCS7_F_SMIME_TEXT,PKCS7_R_MIME_PARSE_ERROR);
+               ASN1err(ASN1_F_SMIME_TEXT,ASN1_R_MIME_PARSE_ERROR);
                return 0;
        }
        if(!(hdr = mime_hdr_find(headers, "content-type")) || !hdr->value) {
-               PKCS7err(PKCS7_F_SMIME_TEXT,PKCS7_R_MIME_NO_CONTENT_TYPE);
+               ASN1err(ASN1_F_SMIME_TEXT,ASN1_R_MIME_NO_CONTENT_TYPE);
                sk_MIME_HEADER_pop_free(headers, mime_hdr_free);
                return 0;
        }
        if (strcmp (hdr->value, "text/plain")) {
-               PKCS7err(PKCS7_F_SMIME_TEXT,PKCS7_R_INVALID_MIME_TYPE);
+               ASN1err(ASN1_F_SMIME_TEXT,ASN1_R_INVALID_MIME_TYPE);
                ERR_add_error_data(2, "type: ", hdr->value);
                sk_MIME_HEADER_pop_free(headers, mime_hdr_free);
                return 0;
index fe2ea40..eb776b7 100644 (file)
@@ -449,13 +449,13 @@ int X509_NAME_print(BIO *bp, X509_NAME *name, int obase)
 
        l=80-2-obase;
 
-       b=s=X509_NAME_oneline(name,NULL,0);
-       if (!*s)
+       b=X509_NAME_oneline(name,NULL,0);
+       if (!*b)
                {
                OPENSSL_free(b);
                return 1;
                }
-       s++; /* skip the first slash */
+       s=b+1; /* skip the first slash */
 
        c=s;
        for (;;)
@@ -480,8 +480,7 @@ int X509_NAME_print(BIO *bp, X509_NAME *name, int obase)
                        {
                        i=s-c;
                        if (BIO_write(bp,c,i) != i) goto err;
-                       c+=i;
-                       c++;
+                       c=s+1;  /* skip following slash */
                        if (*s != '\0')
                                {
                                if (BIO_write(bp,", ",2) != 2) goto err;
index c4a3abe..0ee4062 100644 (file)
@@ -944,7 +944,7 @@ int asn1_ex_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len,
                if (utype != typ->type)
                        ASN1_TYPE_set(typ, utype, NULL);
                opval = pval;
-               pval = (ASN1_VALUE **)&typ->value.ptr;
+               pval = &typ->value.asn1_value;
                }
        switch(utype)
                {
index ed892e2..be19b36 100644 (file)
@@ -597,7 +597,7 @@ int asn1_ex_i2c(ASN1_VALUE **pval, unsigned char *cout, int *putype,
                typ = (ASN1_TYPE *)*pval;
                utype = typ->type;
                *putype = utype;
-               pval = (ASN1_VALUE **)&typ->value.ptr;
+               pval = &typ->value.asn1_value;
                }
        else utype = *putype;
 
index b68b66a..bb7c1e2 100644 (file)
@@ -115,8 +115,6 @@ static void asn1_item_combine_free(ASN1_VALUE **pval, const ASN1_ITEM *it, int c
                                return;
                        }
                i = asn1_get_choice_selector(pval, it);
-               if (asn1_cb)
-                       asn1_cb(ASN1_OP_FREE_PRE, pval, it);
                if ((i >= 0) && (i < it->tcount))
                        {
                        ASN1_VALUE **pchval;
@@ -221,7 +219,7 @@ void ASN1_primitive_free(ASN1_VALUE **pval, const ASN1_ITEM *it)
                {
                ASN1_TYPE *typ = (ASN1_TYPE *)*pval;
                utype = typ->type;
-               pval = (ASN1_VALUE **)&typ->value.ptr;
+               pval = &typ->value.asn1_value;
                if (!*pval)
                        return;
                }
index 00b9ea5..33533ab 100644 (file)
@@ -66,8 +66,65 @@ ASN1_SEQUENCE(X509_ALGOR) = {
        ASN1_OPT(X509_ALGOR, parameter, ASN1_ANY)
 } ASN1_SEQUENCE_END(X509_ALGOR)
 
+ASN1_ITEM_TEMPLATE(X509_ALGORS) = 
+       ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, algorithms, X509_ALGOR)
+ASN1_ITEM_TEMPLATE_END(X509_ALGORS)
+
 IMPLEMENT_ASN1_FUNCTIONS(X509_ALGOR)
+IMPLEMENT_ASN1_ENCODE_FUNCTIONS_fname(X509_ALGORS, X509_ALGORS, X509_ALGORS)
 IMPLEMENT_ASN1_DUP_FUNCTION(X509_ALGOR)
 
 IMPLEMENT_STACK_OF(X509_ALGOR)
 IMPLEMENT_ASN1_SET_OF(X509_ALGOR)
+
+int X509_ALGOR_set0(X509_ALGOR *alg, ASN1_OBJECT *aobj, int ptype, void *pval)
+       {
+       if (!alg)
+               return 0;
+       if (ptype != V_ASN1_UNDEF)
+               {
+               if (alg->parameter == NULL)
+                       alg->parameter = ASN1_TYPE_new();
+               if (alg->parameter == NULL)
+                       return 0;
+               }
+       if (alg)
+               {
+               if (alg->algorithm)
+                       ASN1_OBJECT_free(alg->algorithm);
+               alg->algorithm = aobj;
+               }
+       if (ptype == 0)
+               return 1;       
+       if (ptype == V_ASN1_UNDEF)
+               {
+               if (alg->parameter)
+                       {
+                       ASN1_TYPE_free(alg->parameter);
+                       alg->parameter = NULL;
+                       }
+               }
+       else
+               ASN1_TYPE_set(alg->parameter, ptype, pval);
+       return 1;
+       }
+
+void X509_ALGOR_get0(ASN1_OBJECT **paobj, int *pptype, void **ppval,
+                                               X509_ALGOR *algor)
+       {
+       if (paobj)
+               *paobj = algor->algorithm;
+       if (pptype)
+               {
+               if (algor->parameter == NULL)
+                       {
+                       *pptype = V_ASN1_UNDEF;
+                       return;
+                       }
+               else
+                       *pptype = algor->parameter->type;
+               if (ppval)
+                       *ppval = algor->parameter->value.ptr;
+               }
+       }
+
index 702421b..1732e66 100644 (file)
@@ -67,5 +67,10 @@ ASN1_SEQUENCE(X509_EXTENSION) = {
        ASN1_SIMPLE(X509_EXTENSION, value, ASN1_OCTET_STRING)
 } ASN1_SEQUENCE_END(X509_EXTENSION)
 
+ASN1_ITEM_TEMPLATE(X509_EXTENSIONS) = 
+       ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, Extension, X509_EXTENSION)
+ASN1_ITEM_TEMPLATE_END(X509_EXTENSIONS)
+
 IMPLEMENT_ASN1_FUNCTIONS(X509_EXTENSION)
+IMPLEMENT_ASN1_ENCODE_FUNCTIONS_fname(X509_EXTENSIONS, X509_EXTENSIONS, X509_EXTENSIONS)
 IMPLEMENT_ASN1_DUP_FUNCTION(X509_EXTENSION)
index cd78de1..ead477d 100644 (file)
 #include "cryptlib.h"
 #include <openssl/bio.h>
 #if defined(OPENSSL_SYS_NETWARE) && defined(NETWARE_BSDSOCK)
-#include "netdb.h"
+#include <netdb.h>
+#if defined(NETWARE_CLIB)
+#include <sys/ioctl.h>
+NETDB_DEFINE_CONTEXT
+#endif
 #endif
 
 #ifndef OPENSSL_NO_SOCK
@@ -178,11 +182,11 @@ int BIO_get_port(const char *str, unsigned short *port_ptr)
                /* Note: under VMS with SOCKETSHR, it seems like the first
                 * parameter is 'char *', instead of 'const char *'
                 */
-               s=getservbyname(
 #ifndef CONST_STRICT
-                   (char *)
+               s=getservbyname((char *)str,"tcp");
+#else
+               s=getservbyname(str,"tcp");
 #endif
-                   str,"tcp");
                if(s != NULL)
                        *port_ptr=ntohs((unsigned short)s->s_port);
                CRYPTO_w_unlock(CRYPTO_LOCK_GETSERVBYNAME);
@@ -360,7 +364,11 @@ struct hostent *BIO_gethostbyname(const char *name)
 #if 1
        /* Caching gethostbyname() results forever is wrong,
         * so we have to let the true gethostbyname() worry about this */
+#if (defined(NETWARE_BSDSOCK) && !defined(__NOVELL_LIBC__))
+       return gethostbyname((char*)name);
+#else
        return gethostbyname(name);
+#endif
 #else
        struct hostent *ret;
        int i,lowi=0,j;
@@ -400,11 +408,11 @@ struct hostent *BIO_gethostbyname(const char *name)
                /* Note: under VMS with SOCKETSHR, it seems like the first
                 * parameter is 'char *', instead of 'const char *'
                 */
-               ret=gethostbyname(
 #  ifndef CONST_STRICT
-                   (char *)
+               ret=gethostbyname((char *)name);
+#  else
+               ret=gethostbyname(name);
 #  endif
-                   name);
 
                if (ret == NULL)
                        goto end;
index 0362bb9..cecb6a7 100644 (file)
@@ -95,6 +95,7 @@ extern "C" {
 #define BIO_TYPE_BIO           (19|0x0400)             /* (half a) BIO pair */
 #define BIO_TYPE_LINEBUFFER    (20|0x0200)             /* filter */
 #define BIO_TYPE_DGRAM         (21|0x0400|0x0100)
+#define BIO_TYPE_COMP          (23|0x0200)             /* filter */
 
 #define BIO_TYPE_DESCRIPTOR    0x0100  /* socket, fd, connect or accept */
 #define BIO_TYPE_FILTER                0x0200
index a0cb29b..ea2c3ff 100644 (file)
@@ -208,9 +208,13 @@ static int dgram_write(BIO *b, const char *in, int inl)
        clear_socket_error();
 
     if ( data->connected )
-        ret=send(b->num,in,inl,0);
+        ret=writesocket(b->num,in,inl);
     else
+#if defined(NETWARE_CLIB) && defined(NETWARE_BSDSOCK)
+        ret=sendto(b->num, (char *)in, inl, 0, &data->peer, sizeof(data->peer));
+#else
         ret=sendto(b->num, in, inl, 0, &data->peer, sizeof(data->peer));
+#endif
 
        BIO_clear_retry_flags(b);
        if (ret <= 0)
index b277367..4df9927 100644 (file)
 #include "bio_lcl.h"
 #include <openssl/err.h>
 
+#if defined(OPENSSL_SYS_NETWARE) && defined(NETWARE_CLIB)
+#include <nwfileio.h>
+#endif
+
 #if !defined(OPENSSL_NO_STDIO)
 
 static int MS_CALLBACK file_write(BIO *h, const char *buf, int num);
@@ -285,9 +289,9 @@ static long MS_CALLBACK file_ctrl(BIO *b, int cmd, long num, void *ptr)
          /* Under CLib there are differences in file modes
          */
                if (num & BIO_FP_TEXT)
-                       _setmode(fd,O_TEXT);
+                       setmode(fd,O_TEXT);
                else
-                       _setmode(fd,O_BINARY);
+                       setmode(fd,O_BINARY);
 #elif defined(OPENSSL_SYS_MSDOS)
                int fd = fileno((FILE*)ptr);
                /* Set correct text/binary mode */
index df6eea2..6d754d5 100644 (file)
@@ -303,7 +303,12 @@ struct bn_mont_ctx_st
        BIGNUM N;      /* The modulus */
        BIGNUM Ni;     /* R*(1/R mod N) - N*Ni = 1
                        * (Ni is only stored for bignum algorithm) */
+#if 0
+       /* OpenSSL 0.9.9 preview: */
+       BN_ULONG n0[2];/* least significant word(s) of Ni */
+#else
        BN_ULONG n0;   /* least significant word of Ni */
+#endif
        int flags;
        };
 
index ad4ca7f..27ac439 100644 (file)
@@ -481,6 +481,7 @@ BN_ULONG bn_add_part_words(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b,
        int cl, int dl);
 BN_ULONG bn_sub_part_words(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b,
        int cl, int dl);
+int bn_mul_mont(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp, const BN_ULONG *np,const BN_ULONG *n0, int num);
 
 #ifdef  __cplusplus
 }
index b5d35d1..4799b15 100644 (file)
 
 #define MONT_WORD /* use the faster word-based algorithm */
 
+#if defined(MONT_WORD) && defined(OPENSSL_BN_ASM_MONT) && (BN_BITS2<=32)
+/* This condition means we have a specific non-default build:
+ * In the 0.9.8 branch, OPENSSL_BN_ASM_MONT is normally not set for any
+ * BN_BITS2<=32 platform; an explicit "enable-montasm" is required.
+ * I.e., if we are here, the user intentionally deviates from the
+ * normal stable build to get better Montgomery performance from
+ * the 0.9.9-dev backport.
+ *
+ * In this case only, we also enable BN_from_montgomery_word()
+ * (another non-stable feature from 0.9.9-dev).
+ */
+#define MONT_FROM_WORD___NON_DEFAULT_0_9_8_BUILD
+#endif
+
+#ifdef MONT_FROM_WORD___NON_DEFAULT_0_9_8_BUILD
+static int BN_from_montgomery_word(BIGNUM *ret, BIGNUM *r, BN_MONT_CTX *mont);
+#endif
+
+
+
 int BN_mod_mul_montgomery(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
                          BN_MONT_CTX *mont, BN_CTX *ctx)
        {
        BIGNUM *tmp;
        int ret=0;
+#if defined(OPENSSL_BN_ASM_MONT) && defined(MONT_WORD)
+       int num = mont->N.top;
+
+       if (num>1 && a->top==num && b->top==num)
+               {
+               if (bn_wexpand(r,num) == NULL) return(0);
+#if 0 /* for OpenSSL 0.9.9 mont->n0 */
+               if (bn_mul_mont(r->d,a->d,b->d,mont->N.d,mont->n0,num))
+#else
+               if (bn_mul_mont(r->d,a->d,b->d,mont->N.d,&mont->n0,num))
+#endif
+                       {
+                       r->neg = a->neg^b->neg;
+                       r->top = num;
+                       bn_correct_top(r);
+                       return(1);
+                       }
+               }
+#endif
 
        BN_CTX_start(ctx);
        tmp = BN_CTX_get(ctx);
@@ -142,7 +181,11 @@ int BN_mod_mul_montgomery(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
                if (!BN_mul(tmp,a,b,ctx)) goto err;
                }
        /* reduce from aRR to aR */
+#ifdef MONT_FROM_WORD___NON_DEFAULT_0_9_8_BUILD
+       if (!BN_from_montgomery_word(r,tmp,mont)) goto err;
+#else
        if (!BN_from_montgomery(r,tmp,mont,ctx)) goto err;
+#endif
        bn_check_top(r);
        ret=1;
 err:
@@ -150,6 +193,150 @@ err:
        return(ret);
        }
 
+#ifdef MONT_FROM_WORD___NON_DEFAULT_0_9_8_BUILD
+static int BN_from_montgomery_word(BIGNUM *ret, BIGNUM *r, BN_MONT_CTX *mont)
+       {
+       BIGNUM *n;
+       BN_ULONG *ap,*np,*rp,n0,v,*nrp;
+       int al,nl,max,i,x,ri;
+
+       n= &(mont->N);
+       /* mont->ri is the size of mont->N in bits (rounded up
+          to the word size) */
+       al=ri=mont->ri/BN_BITS2;
+
+       nl=n->top;
+       if ((al == 0) || (nl == 0)) { ret->top=0; return(1); }
+
+       max=(nl+al+1); /* allow for overflow (no?) XXX */
+       if (bn_wexpand(r,max) == NULL) return(0);
+
+       r->neg^=n->neg;
+       np=n->d;
+       rp=r->d;
+       nrp= &(r->d[nl]);
+
+       /* clear the top words of T */
+       for (i=r->top; i<max; i++) /* memset? XXX */
+               r->d[i]=0;
+
+       r->top=max;
+#if 0 /* for OpenSSL 0.9.9 mont->n0 */
+       n0=mont->n0[0];
+#else
+       n0=mont->n0;
+#endif
+
+#ifdef BN_COUNT
+       fprintf(stderr,"word BN_from_montgomery_word %d * %d\n",nl,nl);
+#endif
+       for (i=0; i<nl; i++)
+               {
+#ifdef __TANDEM
+                {
+                   long long t1;
+                   long long t2;
+                   long long t3;
+                   t1 = rp[0] * (n0 & 0177777);
+                   t2 = 037777600000l;
+                   t2 = n0 & t2;
+                   t3 = rp[0] & 0177777;
+                   t2 = (t3 * t2) & BN_MASK2;
+                   t1 = t1 + t2;
+                   v=bn_mul_add_words(rp,np,nl,(BN_ULONG) t1);
+                }
+#else
+               v=bn_mul_add_words(rp,np,nl,(rp[0]*n0)&BN_MASK2);
+#endif
+               nrp++;
+               rp++;
+               if (((nrp[-1]+=v)&BN_MASK2) >= v)
+                       continue;
+               else
+                       {
+                       if (((++nrp[0])&BN_MASK2) != 0) continue;
+                       if (((++nrp[1])&BN_MASK2) != 0) continue;
+                       for (x=2; (((++nrp[x])&BN_MASK2) == 0); x++) ;
+                       }
+               }
+       bn_correct_top(r);
+
+       /* mont->ri will be a multiple of the word size and below code
+        * is kind of BN_rshift(ret,r,mont->ri) equivalent */
+       if (r->top <= ri)
+               {
+               ret->top=0;
+               return(1);
+               }
+       al=r->top-ri;
+
+       if (bn_wexpand(ret,ri) == NULL) return(0);
+       x=0-(((al-ri)>>(sizeof(al)*8-1))&1);
+       ret->top=x=(ri&~x)|(al&x);      /* min(ri,al) */
+       ret->neg=r->neg;
+
+       rp=ret->d;
+       ap=&(r->d[ri]);
+
+       {
+       size_t m1,m2;
+
+       v=bn_sub_words(rp,ap,np,ri);
+       /* this ----------------^^ works even in al<ri case
+        * thanks to zealous zeroing of top of the vector in the
+        * beginning. */
+
+       /* if (al==ri && !v) || al>ri) nrp=rp; else nrp=ap; */
+       /* in other words if subtraction result is real, then
+        * trick unconditional memcpy below to perform in-place
+        * "refresh" instead of actual copy. */
+       m1=0-(size_t)(((al-ri)>>(sizeof(al)*8-1))&1);   /* al<ri */
+       m2=0-(size_t)(((ri-al)>>(sizeof(al)*8-1))&1);   /* al>ri */
+       m1|=m2;                 /* (al!=ri) */
+       m1|=(0-(size_t)v);      /* (al!=ri || v) */
+       m1&=~m2;                /* (al!=ri || v) && !al>ri */
+       nrp=(BN_ULONG *)(((size_t)rp&~m1)|((size_t)ap&m1));
+       }
+
+       /* 'i<ri' is chosen to eliminate dependency on input data, even
+        * though it results in redundant copy in al<ri case. */
+       for (i=0,ri-=4; i<ri; i+=4)
+               {
+               BN_ULONG t1,t2,t3,t4;
+               
+               t1=nrp[i+0];
+               t2=nrp[i+1];
+               t3=nrp[i+2];    ap[i+0]=0;
+               t4=nrp[i+3];    ap[i+1]=0;
+               rp[i+0]=t1;     ap[i+2]=0;
+               rp[i+1]=t2;     ap[i+3]=0;
+               rp[i+2]=t3;
+               rp[i+3]=t4;
+               }
+       for (ri+=4; i<ri; i++)
+               rp[i]=nrp[i], ap[i]=0;
+       bn_correct_top(r);
+       bn_correct_top(ret);
+       bn_check_top(ret);
+
+       return(1);
+       }
+
+int BN_from_montgomery(BIGNUM *ret, const BIGNUM *a, BN_MONT_CTX *mont,
+            BN_CTX *ctx)
+       {
+       int retn=0;
+       BIGNUM *t;
+
+       BN_CTX_start(ctx);
+       if ((t = BN_CTX_get(ctx)) && BN_copy(t,a))
+               retn = BN_from_montgomery_word(ret,t,mont);
+       BN_CTX_end(ctx);
+       return retn;
+       }
+
+#else /* !MONT_FROM_WORD___NON_DEFAULT_0_9_8_BUILD */
+
 int BN_from_montgomery(BIGNUM *ret, const BIGNUM *a, BN_MONT_CTX *mont,
             BN_CTX *ctx)
        {
@@ -342,6 +529,7 @@ int BN_from_montgomery(BIGNUM *ret, const BIGNUM *a, BN_MONT_CTX *mont,
        BN_CTX_end(ctx);
        return(retn);
        }
+#endif /* MONT_FROM_WORD___NON_DEFAULT_0_9_8_BUILD */
 
 BN_MONT_CTX *BN_MONT_CTX_new(void)
        {
@@ -361,6 +549,11 @@ void BN_MONT_CTX_init(BN_MONT_CTX *ctx)
        BN_init(&(ctx->RR));
        BN_init(&(ctx->N));
        BN_init(&(ctx->Ni));
+#if 0 /* for OpenSSL 0.9.9 mont->n0 */
+       ctx->n0[0] = ctx->n0[1] = 0;
+#else
+       ctx->n0 = 0;
+#endif
        ctx->flags=0;
        }
 
@@ -394,14 +587,51 @@ int BN_MONT_CTX_set(BN_MONT_CTX *mont, const BIGNUM *mod, BN_CTX *ctx)
 
                mont->ri=(BN_num_bits(mod)+(BN_BITS2-1))/BN_BITS2*BN_BITS2;
                BN_zero(R);
+#if 0 /* for OpenSSL 0.9.9 mont->n0, would be "#if defined(OPENSSL_BN_ASM_MONT) && (BN_BITS2<=32)",
+         only certain BN_BITS2<=32 platforms actually need this */
+               if (!(BN_set_bit(R,2*BN_BITS2))) goto err;      /* R */
+#else
                if (!(BN_set_bit(R,BN_BITS2))) goto err;        /* R */
+#endif
 
                buf[0]=mod->d[0]; /* tmod = N mod word size */
                buf[1]=0;
+
+               BN_init(&tmod);
                tmod.d=buf;
                tmod.top = buf[0] != 0 ? 1 : 0;
                tmod.dmax=2;
                tmod.neg=0;
+
+#if 0 /* for OpenSSL 0.9.9 mont->n0, would be "#if defined(OPENSSL_BN_ASM_MONT) && (BN_BITS2<=32)";
+         only certain BN_BITS2<=32 platforms actually need this */
+                                                               tmod.top=0;
+               if ((buf[0] = mod->d[0]))                       tmod.top=1;
+               if ((buf[1] = mod->top>1 ? mod->d[1] : 0))      tmod.top=2;
+
+               if ((BN_mod_inverse(Ri,R,&tmod,ctx)) == NULL)
+                       goto err;
+               if (!BN_lshift(Ri,Ri,2*BN_BITS2)) goto err; /* R*Ri */
+               if (!BN_is_zero(Ri))
+                       {
+                       if (!BN_sub_word(Ri,1)) goto err;
+                       }
+               else /* if N mod word size == 1 */
+                       {
+                       if (bn_expand(Ri,(int)sizeof(BN_ULONG)*2) == NULL)
+                               goto err;
+                       /* Ri-- (mod double word size) */
+                       Ri->neg=0;
+                       Ri->d[0]=BN_MASK2;
+                       Ri->d[1]=BN_MASK2;
+                       Ri->top=2;
+                       }
+               if (!BN_div(Ri,NULL,Ri,&tmod,ctx)) goto err;
+               /* Ni = (R*Ri-1)/N,
+                * keep only couple of least significant words: */
+               mont->n0[0] = (Ri->top > 0) ? Ri->d[0] : 0;
+               mont->n0[1] = (Ri->top > 1) ? Ri->d[1] : 0;
+#else
                                                        /* Ri = R^-1 mod N*/
                if ((BN_mod_inverse(Ri,R,&tmod,ctx)) == NULL)
                        goto err;
@@ -417,7 +647,13 @@ int BN_MONT_CTX_set(BN_MONT_CTX *mont, const BIGNUM *mod, BN_CTX *ctx)
                if (!BN_div(Ri,NULL,Ri,&tmod,ctx)) goto err;
                /* Ni = (R*Ri-1)/N,
                 * keep only least significant word: */
+# if 0 /* for OpenSSL 0.9.9 mont->n0 */
+               mont->n0[0] = (Ri->top > 0) ? Ri->d[0] : 0;
+               mont->n0[1] = 0;
+# else
                mont->n0 = (Ri->top > 0) ? Ri->d[0] : 0;
+# endif
+#endif
                }
 #else /* !MONT_WORD */
                { /* bignum version */
@@ -453,7 +689,12 @@ BN_MONT_CTX *BN_MONT_CTX_copy(BN_MONT_CTX *to, BN_MONT_CTX *from)
        if (!BN_copy(&(to->N),&(from->N))) return NULL;
        if (!BN_copy(&(to->Ni),&(from->Ni))) return NULL;
        to->ri=from->ri;
+#if 0 /* for OpenSSL 0.9.9 mont->n0 */
+       to->n0[0]=from->n0[0];
+       to->n0[1]=from->n0[1];
+#else
        to->n0=from->n0;
+#endif
        return(to);
        }
 
index 312b467..b848c8c 100644 (file)
@@ -389,6 +389,7 @@ BN_ULONG bn_add_part_words(BN_ULONG *r,
  * a[0]*b[0]+a[1]*b[1]+(a[0]-a[1])*(b[1]-b[0])
  * a[1]*b[1]
  */
+/* dnX may not be positive, but n2/2+dnX has to be */
 void bn_mul_recursive(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, int n2,
        int dna, int dnb, BN_ULONG *t)
        {
@@ -398,7 +399,7 @@ void bn_mul_recursive(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, int n2,
        BN_ULONG ln,lo,*p;
 
 # ifdef BN_COUNT
-       fprintf(stderr," bn_mul_recursive %d * %d\n",n2,n2);
+       fprintf(stderr," bn_mul_recursive %d%+d * %d%+d\n",n2,dna,n2,dnb);
 # endif
 # ifdef BN_MUL_COMBA
 #  if 0
@@ -545,6 +546,7 @@ void bn_mul_recursive(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, int n2,
 
 /* n+tn is the word length
  * t needs to be n*4 is size, as does r */
+/* tnX may not be negative but less than n */
 void bn_mul_part_recursive(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, int n,
             int tna, int tnb, BN_ULONG *t)
        {
@@ -553,8 +555,8 @@ void bn_mul_part_recursive(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, int n,
        BN_ULONG ln,lo,*p;
 
 # ifdef BN_COUNT
-       fprintf(stderr," bn_mul_part_recursive (%d+%d) * (%d+%d)\n",
-               tna, n, tnb, n);
+       fprintf(stderr," bn_mul_part_recursive (%d%+d) * (%d%+d)\n",
+               n, tna, n, tnb);
 # endif
        if (n < 8)
                {
@@ -655,16 +657,19 @@ void bn_mul_part_recursive(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, int n,
                                for (;;)
                                        {
                                        i/=2;
-                                       if (i <= tna && tna == tnb)
+                                       /* these simplified conditions work
+                                        * exclusively because difference
+                                        * between tna and tnb is 1 or 0 */
+                                       if (i < tna || i < tnb)
                                                {
-                                               bn_mul_recursive(&(r[n2]),
+                                               bn_mul_part_recursive(&(r[n2]),
                                                        &(a[n]),&(b[n]),
                                                        i,tna-i,tnb-i,p);
                                                break;
                                                }
-                                       else if (i < tna || i < tnb)
+                                       else if (i == tna || i == tnb)
                                                {
-                                               bn_mul_part_recursive(&(r[n2]),
+                                               bn_mul_recursive(&(r[n2]),
                                                        &(a[n]),&(b[n]),
                                                        i,tna-i,tnb-i,p);
                                                break;
index f8e306b..e14232f 100644 (file)
@@ -99,41 +99,6 @@ static const BN_ULONG _nist_p_521[] = {0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,
        0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,
        0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,
        0xFFFFFFFF,0x000001FF};
-#elif BN_BITS2 == 16
-static const BN_ULONG _nist_p_192[] = {0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFE,
-       0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF};
-static const BN_ULONG _nist_p_224[] = {0x0001,0x0000,0x0000,0x0000,0x0000,
-       0x0000,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF};
-static const BN_ULONG _nist_p_256[] = {0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,
-       0xFFFF,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0001,0x0000,0xFFFF,
-       0xFFFF};
-static const BN_ULONG _nist_p_384[] = {0xFFFF,0xFFFF,0x0000,0x0000,0x0000,
-       0x0000,0xFFFF,0xFFFF,0xFFFE,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,
-       0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF};
-static const BN_ULONG _nist_p_521[] = {0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,
-       0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,
-       0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,
-       0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0x01FF};
-#elif BN_BITS2 == 8
-static const BN_ULONG _nist_p_192[] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
-       0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
-       0xFF,0xFF};
-static const BN_ULONG _nist_p_224[] = {0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-       0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
-       0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
-static const BN_ULONG _nist_p_256[] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
-       0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-       0x00,0x00,0x01,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF};
-static const BN_ULONG _nist_p_384[] = {0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,
-       0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,
-       0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
-       0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
-static const BN_ULONG _nist_p_521[] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
-       0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
-       0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
-       0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
-       0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
-       0xFF,0x01};
 #endif
 
 const BIGNUM *BN_get0_nist_prime_192(void)
@@ -171,18 +136,7 @@ const BIGNUM *BN_get0_nist_prime_521(void)
        return &const_nist_521;
        }
 
-/* some misc internal functions */
-#if BN_BITS2 != 64
-static BN_ULONG _256_data[BN_NIST_256_TOP*6];
-static int _is_set_256_data = 0;
-static void _init_256_data(void);
-
-static BN_ULONG _384_data[BN_NIST_384_TOP*8];
-static int _is_set_384_data = 0;
-static void _init_384_data(void);
-#endif
-
-#define BN_NIST_ADD_ONE(a)     while (!(++(*(a)))) ++(a);
+#define BN_NIST_ADD_ONE(a)     while (!(*(a)=(*(a)+1)&BN_MASK2)) ++(a);
 
 static void nist_cp_bn_0(BN_ULONG *buf, BN_ULONG *a, int top, int max)
         {
@@ -203,10 +157,10 @@ static void nist_cp_bn(BN_ULONG *buf, BN_ULONG *a, int top)
         }
 
 #if BN_BITS2 == 64
-#define bn_cp_64(to, n, from, m)       (to)[n] = (from)[m];
+#define bn_cp_64(to, n, from, m)       (to)[n] = (m>=0)?((from)[m]):0;
 #define bn_64_set_0(to, n)             (to)[n] = (BN_ULONG)0;
 /* TBD */
-#define bn_cp_32(to, n, from, m)       (to)[n] = (from)[m];
+#define bn_cp_32(to, n, from, m)       (to)[n] = (m>=0)?((from)[m]):0;
 #define bn_32_set_0(to, n)             (to)[n] = (BN_ULONG)0;
 #else
 #define bn_cp_64(to, n, from, m) \
@@ -220,26 +174,8 @@ static void nist_cp_bn(BN_ULONG *buf, BN_ULONG *a, int top)
        bn_32_set_0(to, (n)*2+1); \
        }
 #if BN_BITS2 == 32
-#define bn_cp_32(to, n, from, m)       (to)[n] = (from)[m];
+#define bn_cp_32(to, n, from, m)       (to)[n] = (m>=0)?((from)[m]):0;
 #define bn_32_set_0(to, n)             (to)[n] = (BN_ULONG)0;
-#elif BN_BITS2 == 16
-#define bn_cp_32(to, n, from, m) \
-       { \
-       (to)[(n)*2]   = (from)[(m)*2];  \
-       (to)[(n)*2+1] = (from)[(m)*2+1];\
-       }
-#define bn_32_set_0(to, n) { (to)[(n)*2] = 0; (to)[(n)*2+1] = 0; }
-#elif BN_BITS2 == 8
-#define bn_cp_32(to, n, from, m) \
-       { \
-       (to)[(n)*4]   = (from)[(m)*4];  \
-       (to)[(n)*4+1] = (from)[(m)*4+1];\
-       (to)[(n)*4+2] = (from)[(m)*4+2];\
-       (to)[(n)*4+3] = (from)[(m)*4+3];\
-       }
-#define bn_32_set_0(to, n) \
-       { (to)[(n)*4]   = (BN_ULONG)0; (to)[(n)*4+1] = (BN_ULONG)0; \
-         (to)[(n)*4+2] = (BN_ULONG)0; (to)[(n)*4+3] = (BN_ULONG)0; }
 #endif
 #endif /* BN_BITS2 != 64 */
 
@@ -255,10 +191,13 @@ int BN_nist_mod_192(BIGNUM *r, const BIGNUM *a, const BIGNUM *field,
        BN_CTX *ctx)
        {
        int      top = a->top, i;
-       BN_ULONG carry = 0;
+       int      carry;
        register BN_ULONG *r_d, *a_d = a->d;
        BN_ULONG t_d[BN_NIST_192_TOP],
-                buf[BN_NIST_192_TOP];
+                buf[BN_NIST_192_TOP],
+                c_d[BN_NIST_192_TOP],
+               *res;
+       size_t   mask;
 
        i = BN_ucmp(field, a);
        if (i == 0)
@@ -284,41 +223,28 @@ int BN_nist_mod_192(BIGNUM *r, const BIGNUM *a, const BIGNUM *field,
 
        nist_cp_bn_0(buf, a_d + BN_NIST_192_TOP, top - BN_NIST_192_TOP, BN_NIST_192_TOP);
 
-#if defined(OPENSSL_SYS_VMS) && defined(__DECC)
-# pragma message save
-# pragma message disable BADSUBSCRIPT
-#endif
-
        nist_set_192(t_d, buf, 0, 3, 3);
-       if (bn_add_words(r_d, r_d, t_d, BN_NIST_192_TOP))
-               ++carry;
-
+       carry = bn_add_words(r_d, r_d, t_d, BN_NIST_192_TOP);
+       mask = 0-(size_t)bn_sub_words(c_d,r_d,_nist_p_192,BN_NIST_192_TOP);
+       mask = ~mask | (0-(size_t)carry);
+       res = (BN_ULONG *)(((size_t)c_d&mask) | ((size_t)r_d&~mask));
+       
        nist_set_192(t_d, buf, 4, 4, 0);
-       if (bn_add_words(r_d, r_d, t_d, BN_NIST_192_TOP))
-               ++carry;
-
-#if defined(OPENSSL_SYS_VMS) && defined(__DECC)
-# pragma message restore
-#endif
+       carry = bn_add_words(r_d, res, t_d, BN_NIST_192_TOP);
+       mask = 0-(size_t)bn_sub_words(c_d,r_d,_nist_p_192,BN_NIST_192_TOP);
+       mask = ~mask | (0-(size_t)carry);
+       res = (BN_ULONG *)(((size_t)c_d&mask) | ((size_t)r_d&~mask));
 
        nist_set_192(t_d, buf, 5, 5, 5)
-       if (bn_add_words(r_d, r_d, t_d, BN_NIST_192_TOP))
-               ++carry;
+       carry = bn_add_words(r_d, res, t_d, BN_NIST_192_TOP);
+       mask = 0-(size_t)bn_sub_words(c_d,r_d,_nist_p_192,BN_NIST_192_TOP);
+       mask = ~mask | (0-(size_t)carry);
+       res = (BN_ULONG *)(((size_t)c_d&mask) | ((size_t)r_d&~mask));
 
-       while (carry)
-               {
-               if (bn_sub_words(r_d, r_d, _nist_p_192, BN_NIST_192_TOP))
-                       --carry; 
-               }
+       nist_cp_bn(r_d, res, BN_NIST_192_TOP);
        r->top = BN_NIST_192_TOP;
        bn_correct_top(r);
-       if (BN_ucmp(r, field) >= 0)
-               {
-               bn_sub_words(r_d, r_d, _nist_p_192, BN_NIST_192_TOP);
-               bn_correct_top(r);
-               }
 
-       bn_check_top(r);
        return 1;
        }
 
@@ -336,12 +262,15 @@ int BN_nist_mod_192(BIGNUM *r, const BIGNUM *a, const BIGNUM *field,
 int BN_nist_mod_224(BIGNUM *r, const BIGNUM *a, const BIGNUM *field,
        BN_CTX *ctx)
        {
-#if BN_BITS2 != 64
+#if BN_BITS2 == 32
        int     top = a->top, i;
-       int     carry = 0;
+       int     carry;
        BN_ULONG *r_d, *a_d = a->d;
        BN_ULONG t_d[BN_NIST_224_TOP],
-                buf[BN_NIST_224_TOP];
+                buf[BN_NIST_224_TOP],
+                c_d[BN_NIST_224_TOP],
+               *res;
+       size_t   mask;
 
        i = BN_ucmp(field, a);
        if (i == 0)
@@ -368,65 +297,48 @@ int BN_nist_mod_224(BIGNUM *r, const BIGNUM *a, const BIGNUM *field,
        nist_cp_bn_0(buf, a_d + BN_NIST_224_TOP, top - BN_NIST_224_TOP, BN_NIST_224_TOP);
 
        nist_set_224(t_d, buf, 10, 9, 8, 7, 0, 0, 0);
-       if (bn_add_words(r_d, r_d, t_d, BN_NIST_224_TOP))
-               ++carry;
+       carry = bn_add_words(r_d, r_d, t_d, BN_NIST_224_TOP);
+       mask = 0-(size_t)bn_sub_words(c_d,r_d,_nist_p_224,BN_NIST_224_TOP);
+       mask = ~mask | (0-(size_t)carry);
+       res = (BN_ULONG *)(((size_t)c_d&mask) | ((size_t)r_d&~mask));
+       
        nist_set_224(t_d, buf, 0, 13, 12, 11, 0, 0, 0);
-       if (bn_add_words(r_d, r_d, t_d, BN_NIST_224_TOP))
-               ++carry;
+       carry = bn_add_words(r_d, res, t_d, BN_NIST_224_TOP);
+       mask = 0-(size_t)bn_sub_words(c_d,r_d,_nist_p_224,BN_NIST_224_TOP);
+       mask = ~mask | (0-(size_t)carry);
+       res = (BN_ULONG *)(((size_t)c_d&mask) | ((size_t)r_d&~mask));
+
        nist_set_224(t_d, buf, 13, 12, 11, 10, 9, 8, 7);
-       if (bn_sub_words(r_d, r_d, t_d, BN_NIST_224_TOP))
-               --carry;
+#if BRANCH_FREE
+       carry = bn_sub_words(r_d, res, t_d, BN_NIST_224_TOP);
+       bn_add_words(c_d,r_d,_nist_p_224,BN_NIST_224_TOP);
+       mask = 0-(size_t)carry;
+       res = (BN_ULONG *)(((size_t)c_d&mask) | ((size_t)r_d&~mask));
+#else
+       if (bn_sub_words(r_d, res, t_d, BN_NIST_224_TOP))
+               bn_add_words(r_d,r_d,_nist_p_224,BN_NIST_224_TOP);
+#endif
        nist_set_224(t_d, buf, 0, 0, 0, 0, 13, 12, 11);
-       if (bn_sub_words(r_d, r_d, t_d, BN_NIST_224_TOP))
-               --carry;
-
-       if (carry > 0)
-               while (carry)
-                       {
-                       if (bn_sub_words(r_d,r_d,_nist_p_224,BN_NIST_224_TOP))
-                               --carry;
-                       }
-       else if (carry < 0)
-               while (carry)
-                       {
-                       if (bn_add_words(r_d,r_d,_nist_p_224,BN_NIST_224_TOP))
-                               ++carry;
-                       }
+#if BRANCH_FREE
+       carry = bn_sub_words(r_d, res, t_d, BN_NIST_224_TOP);
+       bn_add_words(c_d,r_d,_nist_p_224,BN_NIST_224_TOP);
+       mask = 0-(size_t)carry;
+       res = (BN_ULONG *)(((size_t)c_d&mask) | ((size_t)r_d&~mask));
 
+       nist_cp_bn(r_d, res, BN_NIST_224_TOP);
+#else
+       if (bn_sub_words(r_d, r_d, t_d, BN_NIST_224_TOP))
+               bn_add_words(r_d,r_d,_nist_p_224,BN_NIST_224_TOP);
+#endif
        r->top = BN_NIST_224_TOP;
        bn_correct_top(r);
-       if (BN_ucmp(r, field) >= 0)
-               {
-               bn_sub_words(r_d, r_d, _nist_p_224, BN_NIST_224_TOP);
-               bn_correct_top(r);
-               }
-       bn_check_top(r);
+
        return 1;
-#else
+#else  /* BN_BITS!=32 */
        return 0;
 #endif
        }
 
-#if BN_BITS2 != 64
-static void _init_256_data(void)
-       {
-       int     i;
-       BN_ULONG *tmp1 = _256_data;
-       const BN_ULONG *tmp2 = tmp1;
-
-       memcpy(tmp1, _nist_p_256, BN_NIST_256_TOP * sizeof(BN_ULONG));
-       tmp1 += BN_NIST_256_TOP;
-
-       for (i=0; i<5; i++)
-               {
-               bn_add_words(tmp1, _nist_p_256, tmp2, BN_NIST_256_TOP);
-               tmp2  = tmp1;
-               tmp1 += BN_NIST_256_TOP;
-               }
-       _is_set_256_data = 1;
-       }
-#endif
-
 #define nist_set_256(to, from, a1, a2, a3, a4, a5, a6, a7, a8) \
        { \
        if (a8 != 0) bn_cp_32(to, 0, from, (a8) - 8) else bn_32_set_0(to, 0)\
@@ -442,24 +354,16 @@ static void _init_256_data(void)
 int BN_nist_mod_256(BIGNUM *r, const BIGNUM *a, const BIGNUM *field,
        BN_CTX *ctx)
        {
-#if BN_BITS2 != 64
+#if BN_BITS2 == 32
        int     i, top = a->top;
        int     carry = 0;
        register BN_ULONG *a_d = a->d, *r_d;
        BN_ULONG t_d[BN_NIST_256_TOP],
-                t_d2[BN_NIST_256_TOP],
-                buf[BN_NIST_256_TOP];
+                buf[BN_NIST_256_TOP],
+                c_d[BN_NIST_256_TOP],
+               *res;
+       size_t   mask;
 
-       if (!_is_set_256_data)
-               {
-               CRYPTO_w_lock(CRYPTO_LOCK_BN);
-               
-               if (!_is_set_256_data)
-                       _init_256_data();
-               
-               CRYPTO_w_unlock(CRYPTO_LOCK_BN);
-               }
-       
        i = BN_ucmp(field, a);
        if (i == 0)
                {
@@ -487,98 +391,91 @@ int BN_nist_mod_256(BIGNUM *r, const BIGNUM *a, const BIGNUM *field,
        /*S1*/
        nist_set_256(t_d, buf, 15, 14, 13, 12, 11, 0, 0, 0);
        /*S2*/
-       nist_set_256(t_d2,buf, 0, 15, 14, 13, 12, 0, 0, 0);
-       if (bn_add_words(t_d, t_d, t_d2, BN_NIST_256_TOP))
-               carry = 2;
-       /* left shift */
-               {
-               register BN_ULONG *ap,t,c;
-               ap = t_d;
-               c=0;
-               for (i = BN_NIST_256_TOP; i != 0; --i)
-                       {
-                       t= *ap;
-                       *(ap++)=((t<<1)|c)&BN_MASK2;
-                       c=(t & BN_TBIT)?1:0;
-                       }
-               if (c)
-                       ++carry;
-               }
+       nist_set_256(c_d,buf, 0, 15, 14, 13, 12, 0, 0, 0);
+       carry = bn_add_words(t_d, t_d, c_d, BN_NIST_256_TOP);
+       mask = 0-(size_t)bn_sub_words(c_d,t_d,_nist_p_256,BN_NIST_256_TOP);
+       mask = ~mask | (0-(size_t)carry);
+       res = (BN_ULONG *)(((size_t)c_d&mask) | ((size_t)t_d&~mask));
+
+       carry = bn_add_words(t_d, res, res, BN_NIST_256_TOP);
+       mask = 0-(size_t)bn_sub_words(c_d,t_d,_nist_p_256,BN_NIST_256_TOP);
+       mask = ~mask | (0-(size_t)carry);
+       res = (BN_ULONG *)(((size_t)c_d&mask) | ((size_t)t_d&~mask));
+
+       carry = bn_add_words(r_d, r_d, res, BN_NIST_256_TOP);
+       mask = 0-(size_t)bn_sub_words(c_d,r_d,_nist_p_256,BN_NIST_256_TOP);
+       mask = ~mask | (0-(size_t)carry);
+       res = (BN_ULONG *)(((size_t)c_d&mask) | ((size_t)r_d&~mask));
 
-       if (bn_add_words(r_d, r_d, t_d, BN_NIST_256_TOP))
-               ++carry;
        /*S3*/
        nist_set_256(t_d, buf, 15, 14, 0, 0, 0, 10, 9, 8);
-       if (bn_add_words(r_d, r_d, t_d, BN_NIST_256_TOP))
-               ++carry;
+       carry = bn_add_words(r_d, res, t_d, BN_NIST_256_TOP);
+       mask = 0-(size_t)bn_sub_words(c_d,r_d,_nist_p_256,BN_NIST_256_TOP);
+       mask = ~mask | (0-(size_t)carry);
+       res = (BN_ULONG *)(((size_t)c_d&mask) | ((size_t)r_d&~mask));
+
        /*S4*/
        nist_set_256(t_d, buf, 8, 13, 15, 14, 13, 11, 10, 9);
-       if (bn_add_words(r_d, r_d, t_d, BN_NIST_256_TOP))
-               ++carry;
+       carry = bn_add_words(r_d, res, t_d, BN_NIST_256_TOP);
+       mask = 0-(size_t)bn_sub_words(c_d,r_d,_nist_p_256,BN_NIST_256_TOP);
+       mask = ~mask | (0-(size_t)carry);
+       res = (BN_ULONG *)(((size_t)c_d&mask) | ((size_t)r_d&~mask));
+
        /*D1*/
        nist_set_256(t_d, buf, 10, 8, 0, 0, 0, 13, 12, 11);
-       if (bn_sub_words(r_d, r_d, t_d, BN_NIST_256_TOP))
-               --carry;
+#if BRANCH_FREE
+       carry = bn_sub_words(r_d, res, t_d, BN_NIST_256_TOP);
+       bn_add_words(c_d,r_d,_nist_p_256,BN_NIST_256_TOP);
+       mask = 0-(size_t)carry;
+       res = (BN_ULONG *)(((size_t)c_d&mask) | ((size_t)r_d&~mask));   
+#else
+       if (bn_sub_words(r_d, res, t_d, BN_NIST_256_TOP))
+               bn_add_words(r_d,r_d,_nist_p_256,BN_NIST_256_TOP);
+#endif
        /*D2*/
        nist_set_256(t_d, buf, 11, 9, 0, 0, 15, 14, 13, 12);
+#if BRANCH_FREE
+       carry = bn_sub_words(r_d, res, t_d, BN_NIST_256_TOP);
+       bn_add_words(c_d,r_d,_nist_p_256,BN_NIST_256_TOP);
+       mask = 0-(size_t)carry;
+       res = (BN_ULONG *)(((size_t)c_d&mask) | ((size_t)r_d&~mask));   
+#else
        if (bn_sub_words(r_d, r_d, t_d, BN_NIST_256_TOP))
-               --carry;
+               bn_add_words(r_d,r_d,_nist_p_256,BN_NIST_256_TOP);
+#endif
        /*D3*/
        nist_set_256(t_d, buf, 12, 0, 10, 9, 8, 15, 14, 13);
+#if BRANCH_FREE
+       carry = bn_sub_words(r_d, res, t_d, BN_NIST_256_TOP);
+       bn_add_words(c_d,r_d,_nist_p_256,BN_NIST_256_TOP);
+       mask = 0-(size_t)carry;
+       res = (BN_ULONG *)(((size_t)c_d&mask) | ((size_t)r_d&~mask));   
+#else
        if (bn_sub_words(r_d, r_d, t_d, BN_NIST_256_TOP))
-               --carry;
+               bn_add_words(r_d,r_d,_nist_p_256,BN_NIST_256_TOP);
+#endif
        /*D4*/
        nist_set_256(t_d, buf, 13, 0, 11, 10, 9, 0, 15, 14);
-       if (bn_sub_words(r_d, r_d, t_d, BN_NIST_256_TOP))
-               --carry;
-       
-       if (carry)
-               {
-               if (carry > 0)
-                       bn_sub_words(r_d, r_d, _256_data + BN_NIST_256_TOP *
-                               --carry, BN_NIST_256_TOP);
-               else
-                       {
-                       carry = -carry;
-                       bn_add_words(r_d, r_d, _256_data + BN_NIST_256_TOP *
-                               --carry, BN_NIST_256_TOP);
-                       }
-               }
+#if BRANCH_FREE
+       carry = bn_sub_words(r_d, res, t_d, BN_NIST_256_TOP);
+       bn_add_words(c_d,r_d,_nist_p_256,BN_NIST_256_TOP);
+       mask = 0-(size_t)carry;
+       res = (BN_ULONG *)(((size_t)c_d&mask) | ((size_t)r_d&~mask));   
 
+       nist_cp_bn(r_d, res, BN_NIST_384_TOP);
+#else
+       if (bn_sub_words(r_d, r_d, t_d, BN_NIST_256_TOP))
+               bn_add_words(r_d,r_d,_nist_p_256,BN_NIST_256_TOP);
+#endif
        r->top = BN_NIST_256_TOP;
        bn_correct_top(r);
-       if (BN_ucmp(r, field) >= 0)
-               {
-               bn_sub_words(r_d, r_d, _nist_p_256, BN_NIST_256_TOP);
-               bn_correct_top(r);
-               }
-       bn_check_top(r);
+
        return 1;
-#else
+#else  /* BN_BITS!=32 */
        return 0;
 #endif
        }
 
-#if BN_BITS2 != 64
-static void _init_384_data(void)
-       {
-       int     i;
-       BN_ULONG *tmp1 = _384_data;
-       const BN_ULONG *tmp2 = tmp1;
-
-       memcpy(tmp1, _nist_p_384, BN_NIST_384_TOP * sizeof(BN_ULONG));
-       tmp1 += BN_NIST_384_TOP;
-
-       for (i=0; i<7; i++)
-               {
-               bn_add_words(tmp1, _nist_p_384, tmp2, BN_NIST_384_TOP);
-               tmp2  = tmp1;
-               tmp1 += BN_NIST_384_TOP;
-               }
-       _is_set_384_data = 1;
-       }
-#endif
-
 #define nist_set_384(to,from,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12) \
        { \
        if (a12 != 0) bn_cp_32(to, 0, from,  (a12) - 12) else bn_32_set_0(to, 0)\
@@ -598,22 +495,15 @@ static void _init_384_data(void)
 int BN_nist_mod_384(BIGNUM *r, const BIGNUM *a, const BIGNUM *field,
        BN_CTX *ctx)
        {
-#if BN_BITS2 != 64
+#if BN_BITS2 == 32
        int     i, top = a->top;
        int     carry = 0;
        register BN_ULONG *r_d, *a_d = a->d;
        BN_ULONG t_d[BN_NIST_384_TOP],
-                buf[BN_NIST_384_TOP];
-
-       if (!_is_set_384_data)
-               {
-               CRYPTO_w_lock(CRYPTO_LOCK_BN);
-               
-               if (!_is_set_384_data)
-                       _init_384_data();
-
-               CRYPTO_w_unlock(CRYPTO_LOCK_BN);
-               }
+                buf[BN_NIST_384_TOP],
+                c_d[BN_NIST_384_TOP],
+               *res;
+       size_t   mask;
 
        i = BN_ucmp(field, a);
        if (i == 0)
@@ -646,72 +536,103 @@ int BN_nist_mod_384(BIGNUM *r, const BIGNUM *a, const BIGNUM *field,
                register BN_ULONG *ap,t,c;
                ap = t_d;
                c=0;
-               for (i = BN_NIST_256_TOP; i != 0; --i)
+               for (i = 3; i != 0; --i)
                        {
                        t= *ap;
                        *(ap++)=((t<<1)|c)&BN_MASK2;
                        c=(t & BN_TBIT)?1:0;
                        }
+               *ap=c;
                }
-       if (bn_add_words(r_d+(128/BN_BITS2), r_d+(128/BN_BITS2), 
-               t_d, BN_NIST_256_TOP))
-               ++carry;
+       carry = bn_add_words(r_d+(128/BN_BITS2), r_d+(128/BN_BITS2), 
+               t_d, BN_NIST_256_TOP);
+       /*
+        * we need if (result>=modulus) subtract(result,modulus);
+        * in n-bit space this can be expressed as
+        * if (carry || result>=modulus) subtract(result,modulus);
+        * the catch is that comparison implies subtraction and
+        * therefore one can write tmp=subtract(result,modulus);
+        * and then if(carry || !borrow) result=tmp; this's what
+        * happens below, but without explicit if:-) a.
+        */
+       mask = 0-(size_t)bn_sub_words(c_d,r_d,_nist_p_384,BN_NIST_384_TOP);
+       mask = ~mask | (0-(size_t)carry);
+       res = (BN_ULONG *)(((size_t)c_d&mask) | ((size_t)r_d&~mask));
+
        /*S2 */
-       if (bn_add_words(r_d, r_d, buf, BN_NIST_384_TOP))
-               ++carry;
+       carry = bn_add_words(r_d, res, buf, BN_NIST_384_TOP);
+       mask = 0-(size_t)bn_sub_words(c_d,r_d,_nist_p_384,BN_NIST_384_TOP);
+       mask = ~mask | (0-(size_t)carry);
+       res = (BN_ULONG *)(((size_t)c_d&mask) | ((size_t)r_d&~mask));
+
        /*S3*/
        nist_set_384(t_d,buf,20,19,18,17,16,15,14,13,12,23,22,21);
-       if (bn_add_words(r_d, r_d, t_d, BN_NIST_384_TOP))
-               ++carry;
+       carry = bn_add_words(r_d, res, t_d, BN_NIST_384_TOP);
+       mask = 0-(size_t)bn_sub_words(c_d,r_d,_nist_p_384,BN_NIST_384_TOP);
+       mask = ~mask | (0-(size_t)carry);
+       res = (BN_ULONG *)(((size_t)c_d&mask) | ((size_t)r_d&~mask));
+
        /*S4*/
        nist_set_384(t_d,buf,19,18,17,16,15,14,13,12,20,0,23,0);
-       if (bn_add_words(r_d, r_d, t_d, BN_NIST_384_TOP))
-               ++carry;
+       carry = bn_add_words(r_d, res, t_d, BN_NIST_384_TOP);
+       mask = 0-(size_t)bn_sub_words(c_d,r_d,_nist_p_384,BN_NIST_384_TOP);
+       mask = ~mask | (0-(size_t)carry);
+       res = (BN_ULONG *)(((size_t)c_d&mask) | ((size_t)r_d&~mask));
+
        /*S5*/
-       nist_set_256(t_d, buf, 0, 0, 0, 0, 23-4, 22-4, 21-4, 20-4);
-       if (bn_add_words(r_d+(128/BN_BITS2), r_d+(128/BN_BITS2), 
-               t_d, BN_NIST_256_TOP))
-               ++carry;
+       nist_set_384(t_d, buf,0,0,0,0,23,22,21,20,0,0,0,0);
+       carry = bn_add_words(r_d, res, t_d, BN_NIST_384_TOP);
+       mask = 0-(size_t)bn_sub_words(c_d,r_d,_nist_p_384,BN_NIST_384_TOP);
+       mask = ~mask | (0-(size_t)carry);
+       res = (BN_ULONG *)(((size_t)c_d&mask) | ((size_t)r_d&~mask));
+
        /*S6*/
        nist_set_384(t_d,buf,0,0,0,0,0,0,23,22,21,0,0,20);
-       if (bn_add_words(r_d, r_d, t_d, BN_NIST_384_TOP))
-               ++carry;
+       carry = bn_add_words(r_d, res, t_d, BN_NIST_384_TOP);
+       mask = 0-(size_t)bn_sub_words(c_d,r_d,_nist_p_384,BN_NIST_384_TOP);
+       mask = ~mask | (0-(size_t)carry);
+       res = (BN_ULONG *)(((size_t)c_d&mask) | ((size_t)r_d&~mask));
+
        /*D1*/
        nist_set_384(t_d,buf,22,21,20,19,18,17,16,15,14,13,12,23);
-       if (bn_sub_words(r_d, r_d, t_d, BN_NIST_384_TOP))
-               --carry;
+#if BRANCH_FREE
+       carry = bn_sub_words(r_d, res, t_d, BN_NIST_384_TOP);
+       bn_add_words(c_d,r_d,_nist_p_384,BN_NIST_384_TOP);
+       mask = 0-(size_t)carry;
+       res = (BN_ULONG *)(((size_t)c_d&mask) | ((size_t)r_d&~mask));
+#else
+       if (bn_sub_words(r_d, res, t_d, BN_NIST_384_TOP))
+               bn_add_words(r_d,r_d,_nist_p_384,BN_NIST_384_TOP);
+#endif
        /*D2*/
        nist_set_384(t_d,buf,0,0,0,0,0,0,0,23,22,21,20,0);
+#if BRANCH_FREE
+       carry = bn_sub_words(r_d, res, t_d, BN_NIST_384_TOP);
+       bn_add_words(c_d,r_d,_nist_p_384,BN_NIST_384_TOP);
+       mask = 0-(size_t)carry;
+       res = (BN_ULONG *)(((size_t)c_d&mask) | ((size_t)r_d&~mask));
+#else
        if (bn_sub_words(r_d, r_d, t_d, BN_NIST_384_TOP))
-               --carry;
+               bn_add_words(r_d,r_d,_nist_p_384,BN_NIST_384_TOP);
+#endif
        /*D3*/
        nist_set_384(t_d,buf,0,0,0,0,0,0,0,23,23,0,0,0);
-       if (bn_sub_words(r_d, r_d, t_d, BN_NIST_384_TOP))
-               --carry;
-       
-       if (carry)
-               {
-               if (carry > 0)
-                       bn_sub_words(r_d, r_d, _384_data + BN_NIST_384_TOP *
-                               --carry, BN_NIST_384_TOP);
-               else
-                       {
-                       carry = -carry;
-                       bn_add_words(r_d, r_d, _384_data + BN_NIST_384_TOP *
-                               --carry, BN_NIST_384_TOP);
-                       }
-               }
+#if BRANCH_FREE
+       carry = bn_sub_words(r_d, res, t_d, BN_NIST_384_TOP);
+       bn_add_words(c_d,r_d,_nist_p_384,BN_NIST_384_TOP);
+       mask = 0-(size_t)carry;
+       res = (BN_ULONG *)(((size_t)c_d&mask) | ((size_t)r_d&~mask));
 
+       nist_cp_bn(r_d, res, BN_NIST_384_TOP);
+#else
+       if (bn_sub_words(r_d, r_d, t_d, BN_NIST_384_TOP))
+               bn_add_words(r_d,r_d,_nist_p_384,BN_NIST_384_TOP);
+#endif
        r->top = BN_NIST_384_TOP;
        bn_correct_top(r);
-       if (BN_ucmp(r, field) >= 0)
-               {
-               bn_sub_words(r_d, r_d, _nist_p_384, BN_NIST_384_TOP);
-               bn_correct_top(r);
-               }
-       bn_check_top(r);
+
        return 1;
-#else
+#else  /* BN_BITS!=32 */
        return 0;
 #endif
        }
@@ -723,10 +644,6 @@ int BN_nist_mod_521(BIGNUM *r, const BIGNUM *a, const BIGNUM *field,
 #define BN_NIST_521_TOP_MASK   (BN_ULONG)0x1FF
 #elif BN_BITS2 == 32
 #define BN_NIST_521_TOP_MASK   (BN_ULONG)0x1FF
-#elif BN_BITS2 == 16
-#define BN_NIST_521_TOP_MASK   (BN_ULONG)0x1FF
-#elif BN_BITS2 == 8
-#define BN_NIST_521_TOP_MASK   (BN_ULONG)0x1
 #endif
        int     top, ret = 0;
        BN_ULONG *r_d;
@@ -762,7 +679,7 @@ int BN_nist_mod_521(BIGNUM *r, const BIGNUM *a, const BIGNUM *field,
            (r_d[BN_NIST_521_TOP-1] & ~(BN_NIST_521_TOP_MASK)))
                {
                BN_NIST_ADD_ONE(r_d)
-               r_d[BN_NIST_521_TOP-1] &= BN_NIST_521_TOP_MASK; 
+               r->d[BN_NIST_521_TOP-1] &= BN_NIST_521_TOP_MASK; 
                }
        bn_correct_top(r);
 
diff --git a/crypto/openssl-0.9/crypto/cms/Makefile b/crypto/openssl-0.9/crypto/cms/Makefile
new file mode 100644 (file)
index 0000000..e39c310
--- /dev/null
@@ -0,0 +1,183 @@
+#
+# OpenSSL/crypto/cms/Makefile
+#
+
+DIR=   cms
+TOP=   ../..
+CC=    cc
+INCLUDES= -I.. -I$(TOP) -I../../include
+CFLAG=-g
+MAKEFILE=      Makefile
+AR=            ar r
+
+CFLAGS= $(INCLUDES) $(CFLAG)
+
+GENERAL=Makefile
+TEST=
+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_enc.c cms_ess.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_enc.o cms_ess.o
+
+SRC= $(LIBSRC)
+
+EXHEADER=  cms.h
+HEADER=        cms_lcl.h $(EXHEADER)
+
+ALL=    $(GENERAL) $(SRC) $(HEADER)
+
+top:
+       (cd ../..; $(MAKE) DIRS=crypto SDIRS=$(DIR) sub_all)
+
+test:
+
+all:   lib
+
+lib:   $(LIBOBJ)
+       $(AR) $(LIB) $(LIBOBJ)
+       $(RANLIB) $(LIB) || echo Never mind.
+       @touch lib
+
+files:
+       $(PERL) $(TOP)/util/files.pl Makefile >> $(TOP)/MINFO
+
+links:
+       @$(PERL) $(TOP)/util/mklink.pl ../../include/openssl $(EXHEADER)
+       @$(PERL) $(TOP)/util/mklink.pl ../../test $(TEST)
+       @$(PERL) $(TOP)/util/mklink.pl ../../apps $(APPS)
+
+install:
+       @[ -n "$(INSTALLTOP)" ] # should be set by top Makefile...
+       @headerlist="$(EXHEADER)"; for i in $$headerlist ; \
+       do  \
+       (cp $$i $(INSTALL_PREFIX)$(INSTALLTOP)/include/openssl/$$i; \
+       chmod 644 $(INSTALL_PREFIX)$(INSTALLTOP)/include/openssl/$$i ); \
+       done;
+
+tags:
+       ctags $(SRC)
+
+tests:
+
+lint:
+       lint -DLINT $(INCLUDES) $(SRC)>fluff
+
+depend:
+       @[ -n "$(MAKEDEPEND)" ] # should be set by upper Makefile...
+       $(MAKEDEPEND) -- $(CFLAG) $(INCLUDES) $(DEPFLAG) -- $(PROGS) $(LIBSRC)
+
+dclean:
+       $(PERL) -pe 'if (/^# DO NOT DELETE THIS LINE/) {print; exit(0);}' $(MAKEFILE) >Makefile.new
+       mv -f Makefile.new $(MAKEFILE)
+
+clean:
+       rm -f *.o *.obj lib tags core .pure .nfs* *.old *.bak fluff
+
+# DO NOT DELETE THIS LINE -- make depend depends on it.
+
+cms_asn1.o: ../../include/openssl/asn1.h ../../include/openssl/asn1t.h
+cms_asn1.o: ../../include/openssl/bio.h ../../include/openssl/buffer.h
+cms_asn1.o: ../../include/openssl/conf.h ../../include/openssl/crypto.h
+cms_asn1.o: ../../include/openssl/e_os2.h ../../include/openssl/ec.h
+cms_asn1.o: ../../include/openssl/ecdh.h ../../include/openssl/ecdsa.h
+cms_asn1.o: ../../include/openssl/evp.h ../../include/openssl/lhash.h
+cms_asn1.o: ../../include/openssl/obj_mac.h ../../include/openssl/objects.h
+cms_asn1.o: ../../include/openssl/opensslconf.h
+cms_asn1.o: ../../include/openssl/opensslv.h ../../include/openssl/ossl_typ.h
+cms_asn1.o: ../../include/openssl/pem.h ../../include/openssl/pem2.h
+cms_asn1.o: ../../include/openssl/pkcs7.h ../../include/openssl/safestack.h
+cms_asn1.o: ../../include/openssl/sha.h ../../include/openssl/stack.h
+cms_asn1.o: ../../include/openssl/symhacks.h ../../include/openssl/x509.h
+cms_asn1.o: ../../include/openssl/x509_vfy.h ../../include/openssl/x509v3.h
+cms_asn1.o: cms.h cms_asn1.c cms_lcl.h
+cms_att.o: ../../include/openssl/asn1.h ../../include/openssl/asn1t.h
+cms_att.o: ../../include/openssl/bio.h ../../include/openssl/buffer.h
+cms_att.o: ../../include/openssl/conf.h ../../include/openssl/crypto.h
+cms_att.o: ../../include/openssl/e_os2.h ../../include/openssl/ec.h
+cms_att.o: ../../include/openssl/ecdh.h ../../include/openssl/ecdsa.h
+cms_att.o: ../../include/openssl/err.h ../../include/openssl/evp.h
+cms_att.o: ../../include/openssl/lhash.h ../../include/openssl/obj_mac.h
+cms_att.o: ../../include/openssl/objects.h ../../include/openssl/opensslconf.h
+cms_att.o: ../../include/openssl/opensslv.h ../../include/openssl/ossl_typ.h
+cms_att.o: ../../include/openssl/pem.h ../../include/openssl/pem2.h
+cms_att.o: ../../include/openssl/pkcs7.h ../../include/openssl/safestack.h
+cms_att.o: ../../include/openssl/sha.h ../../include/openssl/stack.h
+cms_att.o: ../../include/openssl/symhacks.h ../../include/openssl/x509.h
+cms_att.o: ../../include/openssl/x509_vfy.h ../../include/openssl/x509v3.h
+cms_att.o: cms.h cms_att.c cms_lcl.h
+cms_err.o: ../../include/openssl/asn1.h ../../include/openssl/bio.h
+cms_err.o: ../../include/openssl/buffer.h ../../include/openssl/cms.h
+cms_err.o: ../../include/openssl/crypto.h ../../include/openssl/e_os2.h
+cms_err.o: ../../include/openssl/ec.h ../../include/openssl/ecdh.h
+cms_err.o: ../../include/openssl/ecdsa.h ../../include/openssl/err.h
+cms_err.o: ../../include/openssl/evp.h ../../include/openssl/lhash.h
+cms_err.o: ../../include/openssl/obj_mac.h ../../include/openssl/objects.h
+cms_err.o: ../../include/openssl/opensslconf.h ../../include/openssl/opensslv.h
+cms_err.o: ../../include/openssl/ossl_typ.h ../../include/openssl/pkcs7.h
+cms_err.o: ../../include/openssl/safestack.h ../../include/openssl/sha.h
+cms_err.o: ../../include/openssl/stack.h ../../include/openssl/symhacks.h
+cms_err.o: ../../include/openssl/x509.h ../../include/openssl/x509_vfy.h
+cms_err.o: cms_err.c
+cms_io.o: ../../include/openssl/asn1.h ../../include/openssl/asn1t.h
+cms_io.o: ../../include/openssl/bio.h ../../include/openssl/buffer.h
+cms_io.o: ../../include/openssl/crypto.h ../../include/openssl/e_os2.h
+cms_io.o: ../../include/openssl/ec.h ../../include/openssl/ecdh.h
+cms_io.o: ../../include/openssl/ecdsa.h ../../include/openssl/err.h
+cms_io.o: ../../include/openssl/evp.h ../../include/openssl/lhash.h
+cms_io.o: ../../include/openssl/obj_mac.h ../../include/openssl/objects.h
+cms_io.o: ../../include/openssl/opensslconf.h ../../include/openssl/opensslv.h
+cms_io.o: ../../include/openssl/ossl_typ.h ../../include/openssl/pem.h
+cms_io.o: ../../include/openssl/pem2.h ../../include/openssl/pkcs7.h
+cms_io.o: ../../include/openssl/safestack.h ../../include/openssl/sha.h
+cms_io.o: ../../include/openssl/stack.h ../../include/openssl/symhacks.h
+cms_io.o: ../../include/openssl/x509.h ../../include/openssl/x509_vfy.h cms.h
+cms_io.o: cms_io.c cms_lcl.h
+cms_lib.o: ../../include/openssl/asn1.h ../../include/openssl/asn1t.h
+cms_lib.o: ../../include/openssl/bio.h ../../include/openssl/buffer.h
+cms_lib.o: ../../include/openssl/crypto.h ../../include/openssl/e_os2.h
+cms_lib.o: ../../include/openssl/ec.h ../../include/openssl/ecdh.h
+cms_lib.o: ../../include/openssl/ecdsa.h ../../include/openssl/err.h
+cms_lib.o: ../../include/openssl/evp.h ../../include/openssl/lhash.h
+cms_lib.o: ../../include/openssl/obj_mac.h ../../include/openssl/objects.h
+cms_lib.o: ../../include/openssl/opensslconf.h ../../include/openssl/opensslv.h
+cms_lib.o: ../../include/openssl/ossl_typ.h ../../include/openssl/pem.h
+cms_lib.o: ../../include/openssl/pem2.h ../../include/openssl/pkcs7.h
+cms_lib.o: ../../include/openssl/safestack.h ../../include/openssl/sha.h
+cms_lib.o: ../../include/openssl/stack.h ../../include/openssl/symhacks.h
+cms_lib.o: ../../include/openssl/x509.h ../../include/openssl/x509_vfy.h cms.h
+cms_lib.o: cms_lcl.h cms_lib.c
+cms_sd.o: ../../e_os.h ../../include/openssl/asn1.h
+cms_sd.o: ../../include/openssl/asn1t.h ../../include/openssl/bio.h
+cms_sd.o: ../../include/openssl/buffer.h ../../include/openssl/cms.h
+cms_sd.o: ../../include/openssl/conf.h ../../include/openssl/crypto.h
+cms_sd.o: ../../include/openssl/e_os2.h ../../include/openssl/ec.h
+cms_sd.o: ../../include/openssl/ecdh.h ../../include/openssl/ecdsa.h
+cms_sd.o: ../../include/openssl/err.h ../../include/openssl/evp.h
+cms_sd.o: ../../include/openssl/lhash.h ../../include/openssl/obj_mac.h
+cms_sd.o: ../../include/openssl/objects.h ../../include/openssl/opensslconf.h
+cms_sd.o: ../../include/openssl/opensslv.h ../../include/openssl/ossl_typ.h
+cms_sd.o: ../../include/openssl/pem.h ../../include/openssl/pem2.h
+cms_sd.o: ../../include/openssl/pkcs7.h ../../include/openssl/safestack.h
+cms_sd.o: ../../include/openssl/sha.h ../../include/openssl/stack.h
+cms_sd.o: ../../include/openssl/symhacks.h ../../include/openssl/x509.h
+cms_sd.o: ../../include/openssl/x509_vfy.h ../../include/openssl/x509v3.h
+cms_sd.o: ../cryptlib.h cms_lcl.h cms_sd.c
+cms_smime.o: ../../e_os.h ../../include/openssl/asn1.h
+cms_smime.o: ../../include/openssl/asn1t.h ../../include/openssl/bio.h
+cms_smime.o: ../../include/openssl/buffer.h ../../include/openssl/cms.h
+cms_smime.o: ../../include/openssl/conf.h ../../include/openssl/crypto.h
+cms_smime.o: ../../include/openssl/e_os2.h ../../include/openssl/ec.h
+cms_smime.o: ../../include/openssl/ecdh.h ../../include/openssl/ecdsa.h
+cms_smime.o: ../../include/openssl/err.h ../../include/openssl/evp.h
+cms_smime.o: ../../include/openssl/lhash.h ../../include/openssl/obj_mac.h
+cms_smime.o: ../../include/openssl/objects.h
+cms_smime.o: ../../include/openssl/opensslconf.h
+cms_smime.o: ../../include/openssl/opensslv.h ../../include/openssl/ossl_typ.h
+cms_smime.o: ../../include/openssl/pkcs7.h ../../include/openssl/safestack.h
+cms_smime.o: ../../include/openssl/sha.h ../../include/openssl/stack.h
+cms_smime.o: ../../include/openssl/symhacks.h ../../include/openssl/x509.h
+cms_smime.o: ../../include/openssl/x509_vfy.h ../../include/openssl/x509v3.h
+cms_smime.o: ../cryptlib.h cms_lcl.h cms_smime.c
diff --git a/crypto/openssl-0.9/crypto/cms/cms.h b/crypto/openssl-0.9/crypto/cms/cms.h
new file mode 100644 (file)
index 0000000..25f8874
--- /dev/null
@@ -0,0 +1,473 @@
+/* crypto/cms/cms.h */
+/* 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.
+ * ====================================================================
+ */
+
+
+#ifndef HEADER_CMS_H
+#define HEADER_CMS_H
+
+#include <openssl/x509.h>
+
+#ifdef OPENSSL_NO_CMS
+#error CMS is disabled.
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+typedef struct CMS_ContentInfo_st CMS_ContentInfo;
+typedef struct CMS_SignerInfo_st CMS_SignerInfo;
+typedef struct CMS_CertificateChoices CMS_CertificateChoices;
+typedef struct CMS_RevocationInfoChoice_st CMS_RevocationInfoChoice;
+typedef struct CMS_RecipientInfo_st CMS_RecipientInfo;
+typedef struct CMS_ReceiptRequest_st CMS_ReceiptRequest;
+typedef struct CMS_Receipt_st CMS_Receipt;
+
+DECLARE_STACK_OF(CMS_SignerInfo)
+DECLARE_STACK_OF(GENERAL_NAMES)
+DECLARE_ASN1_FUNCTIONS_const(CMS_ContentInfo)
+DECLARE_ASN1_FUNCTIONS_const(CMS_ReceiptRequest)
+
+#define CMS_SIGNERINFO_ISSUER_SERIAL   0
+#define CMS_SIGNERINFO_KEYIDENTIFIER   1
+
+#define CMS_RECIPINFO_TRANS            0
+#define CMS_RECIPINFO_AGREE            1
+#define CMS_RECIPINFO_KEK              2
+#define CMS_RECIPINFO_PASS             3
+#define CMS_RECIPINFO_OTHER            4
+
+/* S/MIME related flags */
+
+#define CMS_TEXT                       0x1
+#define CMS_NOCERTS                    0x2
+#define CMS_NO_CONTENT_VERIFY          0x4
+#define CMS_NO_ATTR_VERIFY             0x8
+#define CMS_NOSIGS                     \
+                       (CMS_NO_CONTENT_VERIFY|CMS_NO_ATTR_VERIFY)
+#define CMS_NOINTERN                   0x10
+#define CMS_NO_SIGNER_CERT_VERIFY      0x20
+#define CMS_NOVERIFY                   0x20
+#define CMS_DETACHED                   0x40
+#define CMS_BINARY                     0x80
+#define CMS_NOATTR                     0x100
+#define        CMS_NOSMIMECAP                  0x200
+#define CMS_NOOLDMIMETYPE              0x400
+#define CMS_CRLFEOL                    0x800
+#define CMS_STREAM                     0x1000
+#define CMS_NOCRL                      0x2000
+#define CMS_PARTIAL                    0x4000
+#define CMS_REUSE_DIGEST               0x8000
+#define CMS_USE_KEYID                  0x10000
+
+const ASN1_OBJECT *CMS_get0_type(CMS_ContentInfo *cms);
+
+BIO *CMS_dataInit(CMS_ContentInfo *cms, BIO *icont);
+int CMS_dataFinal(CMS_ContentInfo *cms, BIO *bio);
+
+ASN1_OCTET_STRING **CMS_get0_content(CMS_ContentInfo *cms);
+int CMS_is_detached(CMS_ContentInfo *cms);
+int CMS_set_detached(CMS_ContentInfo *cms, int detached);
+
+#ifdef HEADER_PEM_H
+DECLARE_PEM_rw_const(CMS, CMS_ContentInfo)
+#endif
+
+CMS_ContentInfo *d2i_CMS_bio(BIO *bp, CMS_ContentInfo **cms);
+int i2d_CMS_bio(BIO *bp, CMS_ContentInfo *cms);
+
+CMS_ContentInfo *SMIME_read_CMS(BIO *bio, BIO **bcont);
+int SMIME_write_CMS(BIO *bio, CMS_ContentInfo *cms, BIO *data, int flags);
+
+int CMS_final(CMS_ContentInfo *cms, BIO *data, BIO *dcont, unsigned int flags);
+
+CMS_ContentInfo *CMS_sign(X509 *signcert, EVP_PKEY *pkey, STACK_OF(X509) *certs,
+                                               BIO *data, unsigned int flags);
+
+CMS_ContentInfo *CMS_sign_receipt(CMS_SignerInfo *si,
+                                       X509 *signcert, EVP_PKEY *pkey,
+                                       STACK_OF(X509) *certs,
+                                       unsigned int flags);
+
+int CMS_data(CMS_ContentInfo *cms, BIO *out, unsigned int flags);
+CMS_ContentInfo *CMS_data_create(BIO *in, unsigned int flags);
+
+int CMS_digest_verify(CMS_ContentInfo *cms, BIO *dcont, BIO *out,
+                                                       unsigned int flags);
+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);
+
+CMS_ContentInfo *CMS_EncryptedData_encrypt(BIO *in, const EVP_CIPHER *cipher,
+                                       const unsigned char *key, size_t keylen,
+                                       unsigned int flags);
+
+int CMS_EncryptedData_set1_key(CMS_ContentInfo *cms, const EVP_CIPHER *ciph,
+                               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);
+
+int CMS_verify_receipt(CMS_ContentInfo *rcms, CMS_ContentInfo *ocms,
+                       STACK_OF(X509) *certs,
+                       X509_STORE *store, unsigned int flags);
+
+STACK_OF(X509) *CMS_get0_signers(CMS_ContentInfo *cms);
+
+CMS_ContentInfo *CMS_encrypt(STACK_OF(X509) *certs, BIO *in,
+                               const EVP_CIPHER *cipher, unsigned int flags);
+
+int CMS_decrypt(CMS_ContentInfo *cms, EVP_PKEY *pkey, X509 *cert,
+                               BIO *dcont, BIO *out,
+                               unsigned int flags);
+       
+int CMS_decrypt_set1_pkey(CMS_ContentInfo *cms, EVP_PKEY *pk, X509 *cert);
+int CMS_decrypt_set1_key(CMS_ContentInfo *cms, 
+                               unsigned char *key, size_t keylen,
+                               unsigned char *id, size_t idlen);
+
+STACK_OF(CMS_RecipientInfo) *CMS_get0_RecipientInfos(CMS_ContentInfo *cms);
+int CMS_RecipientInfo_type(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);
+int CMS_RecipientInfo_set0_pkey(CMS_RecipientInfo *ri, EVP_PKEY *pkey);
+int CMS_RecipientInfo_ktri_cert_cmp(CMS_RecipientInfo *ri, X509 *cert);
+int CMS_RecipientInfo_ktri_get0_algs(CMS_RecipientInfo *ri,
+                                       EVP_PKEY **pk, X509 **recip,
+                                       X509_ALGOR **palg);
+int CMS_RecipientInfo_ktri_get0_signer_id(CMS_RecipientInfo *ri,
+                                       ASN1_OCTET_STRING **keyid,
+                                       X509_NAME **issuer, ASN1_INTEGER **sno);
+
+CMS_RecipientInfo *CMS_add0_recipient_key(CMS_ContentInfo *cms, int nid,
+                                       unsigned char *key, size_t keylen,
+                                       unsigned char *id, size_t idlen,
+                                       ASN1_GENERALIZEDTIME *date,
+                                       ASN1_OBJECT *otherTypeId,
+                                       ASN1_TYPE *otherType);
+
+int CMS_RecipientInfo_kekri_get0_id(CMS_RecipientInfo *ri,
+                                       X509_ALGOR **palg,
+                                       ASN1_OCTET_STRING **pid,
+                                       ASN1_GENERALIZEDTIME **pdate,
+                                       ASN1_OBJECT **potherid,
+                                       ASN1_TYPE **pothertype);
+
+int CMS_RecipientInfo_set0_key(CMS_RecipientInfo *ri, 
+                               unsigned char *key, size_t keylen);
+
+int CMS_RecipientInfo_kekri_id_cmp(CMS_RecipientInfo *ri, 
+                                       const unsigned char *id, size_t idlen);
+
+int CMS_RecipientInfo_decrypt(CMS_ContentInfo *cms, CMS_RecipientInfo *ri);
+       
+int CMS_uncompress(CMS_ContentInfo *cms, BIO *dcont, BIO *out,
+                                                       unsigned int flags);
+CMS_ContentInfo *CMS_compress(BIO *in, int comp_nid, unsigned int flags);
+
+int CMS_set1_eContentType(CMS_ContentInfo *cms, const ASN1_OBJECT *oid);
+const ASN1_OBJECT *CMS_get0_eContentType(CMS_ContentInfo *cms);
+
+CMS_CertificateChoices *CMS_add0_CertificateChoices(CMS_ContentInfo *cms);
+int CMS_add0_cert(CMS_ContentInfo *cms, X509 *cert);
+int CMS_add1_cert(CMS_ContentInfo *cms, X509 *cert);
+STACK_OF(X509) *CMS_get1_certs(CMS_ContentInfo *cms);
+
+CMS_RevocationInfoChoice *CMS_add0_RevocationInfoChoice(CMS_ContentInfo *cms);
+int CMS_add0_crl(CMS_ContentInfo *cms, X509_CRL *crl);
+STACK_OF(X509_CRL) *CMS_get1_crls(CMS_ContentInfo *cms);
+
+int CMS_SignedData_init(CMS_ContentInfo *cms);
+CMS_SignerInfo *CMS_add1_signer(CMS_ContentInfo *cms,
+                       X509 *signer, EVP_PKEY *pk, const EVP_MD *md,
+                       unsigned int flags);
+STACK_OF(CMS_SignerInfo) *CMS_get0_SignerInfos(CMS_ContentInfo *cms);
+
+void CMS_SignerInfo_set1_signer_cert(CMS_SignerInfo *si, X509 *signer);
+int CMS_SignerInfo_get0_signer_id(CMS_SignerInfo *si,
+                                       ASN1_OCTET_STRING **keyid,
+                                       X509_NAME **issuer, ASN1_INTEGER **sno);
+int CMS_SignerInfo_cert_cmp(CMS_SignerInfo *si, X509 *cert);
+int CMS_set1_signers_certs(CMS_ContentInfo *cms, STACK_OF(X509) *certs,
+                                       unsigned int flags);
+void CMS_SignerInfo_get0_algs(CMS_SignerInfo *si, EVP_PKEY **pk, X509 **signer,
+                                       X509_ALGOR **pdig, X509_ALGOR **psig);
+int CMS_SignerInfo_sign(CMS_SignerInfo *si);
+int CMS_SignerInfo_verify(CMS_SignerInfo *si);
+int CMS_SignerInfo_verify_content(CMS_SignerInfo *si, BIO *chain);
+
+int CMS_add_smimecap(CMS_SignerInfo *si, STACK_OF(X509_ALGOR) *algs);
+int CMS_add_simple_smimecap(STACK_OF(X509_ALGOR) **algs,
+                               int algnid, int keysize);
+int CMS_add_standard_smimecap(STACK_OF(X509_ALGOR) **smcap);
+
+int CMS_signed_get_attr_count(const CMS_SignerInfo *si);
+int CMS_signed_get_attr_by_NID(const CMS_SignerInfo *si, int nid,
+                         int lastpos);
+int CMS_signed_get_attr_by_OBJ(const CMS_SignerInfo *si, ASN1_OBJECT *obj,
+                         int lastpos);
+X509_ATTRIBUTE *CMS_signed_get_attr(const CMS_SignerInfo *si, int loc);
+X509_ATTRIBUTE *CMS_signed_delete_attr(CMS_SignerInfo *si, int loc);
+int CMS_signed_add1_attr(CMS_SignerInfo *si, X509_ATTRIBUTE *attr);
+int CMS_signed_add1_attr_by_OBJ(CMS_SignerInfo *si,
+                       const ASN1_OBJECT *obj, int type,
+                       const void *bytes, int len);
+int CMS_signed_add1_attr_by_NID(CMS_SignerInfo *si,
+                       int nid, int type,
+                       const void *bytes, int len);
+int CMS_signed_add1_attr_by_txt(CMS_SignerInfo *si,
+                       const char *attrname, int type,
+                       const void *bytes, int len);
+void *CMS_signed_get0_data_by_OBJ(CMS_SignerInfo *si, ASN1_OBJECT *oid,
+                                       int lastpos, int type);
+
+int CMS_unsigned_get_attr_count(const CMS_SignerInfo *si);
+int CMS_unsigned_get_attr_by_NID(const CMS_SignerInfo *si, int nid,
+                         int lastpos);
+int CMS_unsigned_get_attr_by_OBJ(const CMS_SignerInfo *si, ASN1_OBJECT *obj,
+                         int lastpos);
+X509_ATTRIBUTE *CMS_unsigned_get_attr(const CMS_SignerInfo *si, int loc);
+X509_ATTRIBUTE *CMS_unsigned_delete_attr(CMS_SignerInfo *si, int loc);
+int CMS_unsigned_add1_attr(CMS_SignerInfo *si, X509_ATTRIBUTE *attr);
+int CMS_unsigned_add1_attr_by_OBJ(CMS_SignerInfo *si,
+                       const ASN1_OBJECT *obj, int type,
+                       const void *bytes, int len);
+int CMS_unsigned_add1_attr_by_NID(CMS_SignerInfo *si,
+                       int nid, int type,
+                       const void *bytes, int len);
+int CMS_unsigned_add1_attr_by_txt(CMS_SignerInfo *si,
+                       const char *attrname, int type,
+                       const void *bytes, int len);
+void *CMS_unsigned_get0_data_by_OBJ(CMS_SignerInfo *si, ASN1_OBJECT *oid,
+                                       int lastpos, int type);
+
+#ifdef HEADER_X509V3_H
+
+int CMS_get1_ReceiptRequest(CMS_SignerInfo *si, CMS_ReceiptRequest **prr);
+CMS_ReceiptRequest *CMS_ReceiptRequest_create0(unsigned char *id, int idlen,
+                               int allorfirst,
+                               STACK_OF(GENERAL_NAMES) *receiptList,
+                               STACK_OF(GENERAL_NAMES) *receiptsTo);
+int CMS_add1_ReceiptRequest(CMS_SignerInfo *si, CMS_ReceiptRequest *rr);
+void CMS_ReceiptRequest_get0_values(CMS_ReceiptRequest *rr,
+                                       ASN1_STRING **pcid,
+                                       int *pallorfirst,
+                                       STACK_OF(GENERAL_NAMES) **plist,
+                                       STACK_OF(GENERAL_NAMES) **prto);
+
+#endif
+
+/* BEGIN ERROR CODES */
+/* The following lines are auto generated by the script mkerr.pl. Any changes
+ * made after this point may be overwritten when the script is next run.
+ */
+void ERR_load_CMS_strings(void);
+
+/* Error codes for the CMS functions. */
+
+/* Function codes. */
+#define CMS_F_CHECK_CONTENT                             99
+#define CMS_F_CMS_ADD0_CERT                             164
+#define CMS_F_CMS_ADD0_RECIPIENT_KEY                    100
+#define CMS_F_CMS_ADD1_RECEIPTREQUEST                   158
+#define CMS_F_CMS_ADD1_RECIPIENT_CERT                   101
+#define CMS_F_CMS_ADD1_SIGNER                           102
+#define CMS_F_CMS_ADD1_SIGNINGTIME                      103
+#define CMS_F_CMS_COMPRESS                              104
+#define CMS_F_CMS_COMPRESSEDDATA_CREATE                         105
+#define CMS_F_CMS_COMPRESSEDDATA_INIT_BIO               106
+#define CMS_F_CMS_COPY_CONTENT                          107
+#define CMS_F_CMS_COPY_MESSAGEDIGEST                    108
+#define CMS_F_CMS_DATA                                  109
+#define CMS_F_CMS_DATAFINAL                             110
+#define CMS_F_CMS_DATAINIT                              111
+#define CMS_F_CMS_DECRYPT                               112
+#define CMS_F_CMS_DECRYPT_SET1_KEY                      113
+#define CMS_F_CMS_DECRYPT_SET1_PKEY                     114
+#define CMS_F_CMS_DIGESTALGORITHM_FIND_CTX              115
+#define CMS_F_CMS_DIGESTALGORITHM_INIT_BIO              116
+#define CMS_F_CMS_DIGESTEDDATA_DO_FINAL                         117
+#define CMS_F_CMS_DIGEST_VERIFY                                 118
+#define CMS_F_CMS_ENCODE_RECEIPT                        161
+#define CMS_F_CMS_ENCRYPT                               119
+#define CMS_F_CMS_ENCRYPTEDCONTENT_INIT_BIO             120
+#define CMS_F_CMS_ENCRYPTEDDATA_DECRYPT                         121
+#define CMS_F_CMS_ENCRYPTEDDATA_ENCRYPT                         122
+#define CMS_F_CMS_ENCRYPTEDDATA_SET1_KEY                123
+#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_FINAL                                         127
+#define CMS_F_CMS_GET0_CERTIFICATE_CHOICES              128
+#define CMS_F_CMS_GET0_CONTENT                          129
+#define CMS_F_CMS_GET0_ECONTENT_TYPE                    130
+#define CMS_F_CMS_GET0_ENVELOPED                        131
+#define CMS_F_CMS_GET0_REVOCATION_CHOICES               132
+#define CMS_F_CMS_GET0_SIGNED                           133
+#define CMS_F_CMS_MSGSIGDIGEST_ADD1                     162
+#define CMS_F_CMS_RECEIPTREQUEST_CREATE0                159
+#define CMS_F_CMS_RECEIPT_VERIFY                        160
+#define CMS_F_CMS_RECIPIENTINFO_DECRYPT                         134
+#define CMS_F_CMS_RECIPIENTINFO_KEKRI_DECRYPT           135
+#define CMS_F_CMS_RECIPIENTINFO_KEKRI_ENCRYPT           136
+#define CMS_F_CMS_RECIPIENTINFO_KEKRI_GET0_ID           137
+#define CMS_F_CMS_RECIPIENTINFO_KEKRI_ID_CMP            138
+#define CMS_F_CMS_RECIPIENTINFO_KTRI_CERT_CMP           139
+#define CMS_F_CMS_RECIPIENTINFO_KTRI_DECRYPT            140
+#define CMS_F_CMS_RECIPIENTINFO_KTRI_ENCRYPT            141
+#define CMS_F_CMS_RECIPIENTINFO_KTRI_GET0_ALGS          142
+#define CMS_F_CMS_RECIPIENTINFO_KTRI_GET0_SIGNER_ID     143
+#define CMS_F_CMS_RECIPIENTINFO_SET0_KEY                144
+#define CMS_F_CMS_RECIPIENTINFO_SET0_PKEY               145
+#define CMS_F_CMS_SET1_SIGNERIDENTIFIER                         146
+#define CMS_F_CMS_SET_DETACHED                          147
+#define CMS_F_CMS_SIGN                                  148
+#define CMS_F_CMS_SIGNED_DATA_INIT                      149
+#define CMS_F_CMS_SIGNERINFO_CONTENT_SIGN               150
+#define CMS_F_CMS_SIGNERINFO_SIGN                       151
+#define CMS_F_CMS_SIGNERINFO_VERIFY                     152
+#define CMS_F_CMS_SIGNERINFO_VERIFY_CERT                153
+#define CMS_F_CMS_SIGNERINFO_VERIFY_CONTENT             154
+#define CMS_F_CMS_SIGN_RECEIPT                          163
+#define CMS_F_CMS_STREAM                                155
+#define CMS_F_CMS_UNCOMPRESS                            156
+#define CMS_F_CMS_VERIFY                                157
+
+/* Reason codes. */
+#define CMS_R_ADD_SIGNER_ERROR                          99
+#define CMS_R_CERTIFICATE_ALREADY_PRESENT               175
+#define CMS_R_CERTIFICATE_HAS_NO_KEYID                  160
+#define CMS_R_CERTIFICATE_VERIFY_ERROR                  100
+#define CMS_R_CIPHER_INITIALISATION_ERROR               101
+#define CMS_R_CIPHER_PARAMETER_INITIALISATION_ERROR     102
+#define CMS_R_CMS_DATAFINAL_ERROR                       103
+#define CMS_R_CMS_LIB                                   104
+#define CMS_R_CONTENTIDENTIFIER_MISMATCH                170
+#define CMS_R_CONTENT_NOT_FOUND                                 105
+#define CMS_R_CONTENT_TYPE_MISMATCH                     171
+#define CMS_R_CONTENT_TYPE_NOT_COMPRESSED_DATA          106
+#define CMS_R_CONTENT_TYPE_NOT_ENVELOPED_DATA           107
+#define CMS_R_CONTENT_TYPE_NOT_SIGNED_DATA              108
+#define CMS_R_CONTENT_VERIFY_ERROR                      109
+#define CMS_R_CTRL_ERROR                                110
+#define CMS_R_CTRL_FAILURE                              111
+#define CMS_R_DECRYPT_ERROR                             112
+#define CMS_R_DIGEST_ERROR                              161
+#define CMS_R_ERROR_GETTING_PUBLIC_KEY                  113
+#define CMS_R_ERROR_READING_MESSAGEDIGEST_ATTRIBUTE     114
+#define CMS_R_ERROR_SETTING_KEY                                 115
+#define CMS_R_ERROR_SETTING_RECIPIENTINFO               116
+#define CMS_R_INVALID_ENCRYPTED_KEY_LENGTH              117
+#define CMS_R_INVALID_KEY_LENGTH                        118
+#define CMS_R_MD_BIO_INIT_ERROR                                 119
+#define CMS_R_MESSAGEDIGEST_ATTRIBUTE_WRONG_LENGTH      120
+#define CMS_R_MESSAGEDIGEST_WRONG_LENGTH                121
+#define CMS_R_MSGSIGDIGEST_ERROR                        172
+#define CMS_R_MSGSIGDIGEST_VERIFICATION_FAILURE                 162
+#define CMS_R_MSGSIGDIGEST_WRONG_LENGTH                         163
+#define CMS_R_NEED_ONE_SIGNER                           164
+#define CMS_R_NOT_A_SIGNED_RECEIPT                      165
+#define CMS_R_NOT_ENCRYPTED_DATA                        122
+#define CMS_R_NOT_KEK                                   123
+#define CMS_R_NOT_KEY_TRANSPORT                                 124
+#define CMS_R_NOT_SUPPORTED_FOR_THIS_KEY_TYPE           125
+#define CMS_R_NO_CIPHER                                         126
+#define CMS_R_NO_CONTENT                                127
+#define CMS_R_NO_CONTENT_TYPE                           173
+#define CMS_R_NO_DEFAULT_DIGEST                                 128
+#define CMS_R_NO_DIGEST_SET                             129
+#define CMS_R_NO_KEY                                    130
+#define CMS_R_NO_KEY_OR_CERT                            174
+#define CMS_R_NO_MATCHING_DIGEST                        131
+#define CMS_R_NO_MATCHING_RECIPIENT                     132
+#define CMS_R_NO_MATCHING_SIGNATURE                     166
+#define CMS_R_NO_MSGSIGDIGEST                           167
+#define CMS_R_NO_PRIVATE_KEY                            133
+#define CMS_R_NO_PUBLIC_KEY                             134
+#define CMS_R_NO_RECEIPT_REQUEST                        168
+#define CMS_R_NO_SIGNERS                                135
+#define CMS_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE    136
+#define CMS_R_RECEIPT_DECODE_ERROR                      169
+#define CMS_R_RECIPIENT_ERROR                           137
+#define CMS_R_SIGNER_CERTIFICATE_NOT_FOUND              138
+#define CMS_R_SIGNFINAL_ERROR                           139
+#define CMS_R_SMIME_TEXT_ERROR                          140
+#define CMS_R_STORE_INIT_ERROR                          141
+#define CMS_R_TYPE_NOT_COMPRESSED_DATA                  142
+#define CMS_R_TYPE_NOT_DATA                             143
+#define CMS_R_TYPE_NOT_DIGESTED_DATA                    144
+#define CMS_R_TYPE_NOT_ENCRYPTED_DATA                   145
+#define CMS_R_TYPE_NOT_ENVELOPED_DATA                   146
+#define CMS_R_UNABLE_TO_FINALIZE_CONTEXT                147
+#define CMS_R_UNKNOWN_CIPHER                            148
+#define CMS_R_UNKNOWN_DIGEST_ALGORIHM                   149
+#define CMS_R_UNKNOWN_ID                                150
+#define CMS_R_UNSUPPORTED_COMPRESSION_ALGORITHM                 151
+#define CMS_R_UNSUPPORTED_CONTENT_TYPE                  152
+#define CMS_R_UNSUPPORTED_KEK_ALGORITHM                         153
+#define CMS_R_UNSUPPORTED_RECIPIENT_TYPE                154
+#define CMS_R_UNSUPPORTED_RECPIENTINFO_TYPE             155
+#define CMS_R_UNSUPPORTED_TYPE                          156
+#define CMS_R_UNWRAP_ERROR                              157
+#define CMS_R_VERIFICATION_FAILURE                      158
+#define CMS_R_WRAP_ERROR                                159
+
+#ifdef  __cplusplus
+}
+#endif
+#endif
diff --git a/crypto/openssl-0.9/crypto/cms/cms_asn1.c b/crypto/openssl-0.9/crypto/cms/cms_asn1.c
new file mode 100644 (file)
index 0000000..7664921
--- /dev/null
@@ -0,0 +1,346 @@
+/* crypto/cms/cms_asn1.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 <openssl/asn1t.h>
+#include <openssl/pem.h>
+#include <openssl/x509v3.h>
+#include "cms.h"
+#include "cms_lcl.h"
+
+
+ASN1_SEQUENCE(CMS_IssuerAndSerialNumber) = {
+       ASN1_SIMPLE(CMS_IssuerAndSerialNumber, issuer, X509_NAME),
+       ASN1_SIMPLE(CMS_IssuerAndSerialNumber, serialNumber, ASN1_INTEGER)
+} ASN1_SEQUENCE_END(CMS_IssuerAndSerialNumber)
+
+ASN1_SEQUENCE(CMS_OtherCertificateFormat) = {
+       ASN1_SIMPLE(CMS_OtherCertificateFormat, otherCertFormat, ASN1_OBJECT),
+       ASN1_OPT(CMS_OtherCertificateFormat, otherCert, ASN1_ANY)
+} ASN1_SEQUENCE_END(CMS_OtherCertificateFormat)
+
+ASN1_CHOICE(CMS_CertificateChoices) = {
+       ASN1_SIMPLE(CMS_CertificateChoices, d.certificate, X509),
+       ASN1_IMP(CMS_CertificateChoices, d.extendedCertificate, ASN1_SEQUENCE, 0),
+       ASN1_IMP(CMS_CertificateChoices, d.v1AttrCert, ASN1_SEQUENCE, 1),
+       ASN1_IMP(CMS_CertificateChoices, d.v2AttrCert, ASN1_SEQUENCE, 2),
+       ASN1_IMP(CMS_CertificateChoices, d.other, CMS_OtherCertificateFormat, 3)
+} ASN1_CHOICE_END(CMS_CertificateChoices)
+
+ASN1_CHOICE(CMS_SignerIdentifier) = {
+       ASN1_SIMPLE(CMS_SignerIdentifier, d.issuerAndSerialNumber, CMS_IssuerAndSerialNumber),
+       ASN1_IMP(CMS_SignerIdentifier, d.subjectKeyIdentifier, ASN1_OCTET_STRING, 0)
+} ASN1_CHOICE_END(CMS_SignerIdentifier)
+
+ASN1_NDEF_SEQUENCE(CMS_EncapsulatedContentInfo) = {
+       ASN1_SIMPLE(CMS_EncapsulatedContentInfo, eContentType, ASN1_OBJECT),
+       ASN1_NDEF_EXP_OPT(CMS_EncapsulatedContentInfo, eContent, ASN1_OCTET_STRING_NDEF, 0)
+} ASN1_NDEF_SEQUENCE_END(CMS_EncapsulatedContentInfo)
+
+/* Minor tweak to operation: free up signer key, cert */
+static int cms_si_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it)
+       {
+       if(operation == ASN1_OP_FREE_POST)
+               {
+               CMS_SignerInfo *si = (CMS_SignerInfo *)*pval;
+               if (si->pkey)
+                       EVP_PKEY_free(si->pkey);
+               if (si->signer)
+                       X509_free(si->signer);
+               }
+       return 1;
+       }
+
+ASN1_SEQUENCE_cb(CMS_SignerInfo, cms_si_cb) = {
+       ASN1_SIMPLE(CMS_SignerInfo, version, LONG),
+       ASN1_SIMPLE(CMS_SignerInfo, sid, CMS_SignerIdentifier),
+       ASN1_SIMPLE(CMS_SignerInfo, digestAlgorithm, X509_ALGOR),
+       ASN1_IMP_SET_OF_OPT(CMS_SignerInfo, signedAttrs, X509_ATTRIBUTE, 0),
+       ASN1_SIMPLE(CMS_SignerInfo, signatureAlgorithm, X509_ALGOR),
+       ASN1_SIMPLE(CMS_SignerInfo, signature, ASN1_OCTET_STRING),
+       ASN1_IMP_SET_OF_OPT(CMS_SignerInfo, unsignedAttrs, X509_ATTRIBUTE, 1)
+} ASN1_SEQUENCE_END_cb(CMS_SignerInfo, CMS_SignerInfo)
+
+ASN1_SEQUENCE(CMS_OtherRevocationInfoFormat) = {
+       ASN1_SIMPLE(CMS_OtherRevocationInfoFormat, otherRevInfoFormat, ASN1_OBJECT),
+       ASN1_OPT(CMS_OtherRevocationInfoFormat, otherRevInfo, ASN1_ANY)
+} ASN1_SEQUENCE_END(CMS_OtherRevocationInfoFormat)
+
+ASN1_CHOICE(CMS_RevocationInfoChoice) = {
+       ASN1_SIMPLE(CMS_RevocationInfoChoice, d.crl, X509_CRL),
+       ASN1_IMP(CMS_RevocationInfoChoice, d.other, CMS_OtherRevocationInfoFormat, 1)
+} ASN1_CHOICE_END(CMS_RevocationInfoChoice)
+
+ASN1_NDEF_SEQUENCE(CMS_SignedData) = {
+       ASN1_SIMPLE(CMS_SignedData, version, LONG),
+       ASN1_SET_OF(CMS_SignedData, digestAlgorithms, X509_ALGOR),
+       ASN1_SIMPLE(CMS_SignedData, encapContentInfo, CMS_EncapsulatedContentInfo),
+       ASN1_IMP_SET_OF_OPT(CMS_SignedData, certificates, CMS_CertificateChoices, 0),
+       ASN1_IMP_SET_OF_OPT(CMS_SignedData, crls, CMS_RevocationInfoChoice, 1),
+       ASN1_SET_OF(CMS_SignedData, signerInfos, CMS_SignerInfo)
+} 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_SEQUENCE_END(CMS_OriginatorInfo)
+
+ASN1_NDEF_SEQUENCE(CMS_EncryptedContentInfo) = {
+       ASN1_SIMPLE(CMS_EncryptedContentInfo, contentType, ASN1_OBJECT),
+       ASN1_SIMPLE(CMS_EncryptedContentInfo, contentEncryptionAlgorithm, X509_ALGOR),
+       ASN1_IMP_OPT(CMS_EncryptedContentInfo, encryptedContent, ASN1_OCTET_STRING_NDEF, 0)
+} ASN1_NDEF_SEQUENCE_END(CMS_EncryptedContentInfo)
+
+ASN1_SEQUENCE(CMS_KeyTransRecipientInfo) = {
+       ASN1_SIMPLE(CMS_KeyTransRecipientInfo, version, LONG),
+       ASN1_SIMPLE(CMS_KeyTransRecipientInfo, rid, CMS_SignerIdentifier),
+       ASN1_SIMPLE(CMS_KeyTransRecipientInfo, keyEncryptionAlgorithm, X509_ALGOR),
+       ASN1_SIMPLE(CMS_KeyTransRecipientInfo, encryptedKey, ASN1_OCTET_STRING)
+} ASN1_SEQUENCE_END(CMS_KeyTransRecipientInfo)
+
+ASN1_SEQUENCE(CMS_OtherKeyAttribute) = {
+       ASN1_SIMPLE(CMS_OtherKeyAttribute, keyAttrId, ASN1_OBJECT),
+       ASN1_OPT(CMS_OtherKeyAttribute, keyAttr, ASN1_ANY)
+} ASN1_SEQUENCE_END(CMS_OtherKeyAttribute)
+
+ASN1_SEQUENCE(CMS_RecipientKeyIdentifier) = {
+       ASN1_SIMPLE(CMS_RecipientKeyIdentifier, subjectKeyIdentifier, ASN1_OCTET_STRING),
+       ASN1_OPT(CMS_RecipientKeyIdentifier, date, ASN1_GENERALIZEDTIME),
+       ASN1_OPT(CMS_RecipientKeyIdentifier, other, CMS_OtherKeyAttribute)
+} ASN1_SEQUENCE_END(CMS_RecipientKeyIdentifier)
+
+ASN1_CHOICE(CMS_KeyAgreeRecipientIdentifier) = {
+  ASN1_SIMPLE(CMS_KeyAgreeRecipientIdentifier, d.issuerAndSerialNumber, CMS_IssuerAndSerialNumber),
+  ASN1_IMP(CMS_KeyAgreeRecipientIdentifier, d.rKeyId, CMS_RecipientKeyIdentifier, 0)
+} ASN1_CHOICE_END(CMS_KeyAgreeRecipientIdentifier)
+
+ASN1_SEQUENCE(CMS_RecipientEncryptedKey) = {
+       ASN1_SIMPLE(CMS_RecipientEncryptedKey, rid, CMS_KeyAgreeRecipientIdentifier),
+       ASN1_SIMPLE(CMS_RecipientEncryptedKey, encryptedKey, ASN1_OCTET_STRING)
+} ASN1_SEQUENCE_END(CMS_RecipientEncryptedKey)
+
+ASN1_SEQUENCE(CMS_OriginatorPublicKey) = {
+  ASN1_SIMPLE(CMS_OriginatorPublicKey, algorithm, X509_ALGOR),
+  ASN1_SIMPLE(CMS_OriginatorPublicKey, publicKey, ASN1_BIT_STRING)
+} ASN1_SEQUENCE_END(CMS_OriginatorPublicKey)
+
+ASN1_CHOICE(CMS_OriginatorIdentifierOrKey) = {
+  ASN1_SIMPLE(CMS_OriginatorIdentifierOrKey, d.issuerAndSerialNumber, CMS_IssuerAndSerialNumber),
+  ASN1_IMP(CMS_OriginatorIdentifierOrKey, d.subjectKeyIdentifier, ASN1_OCTET_STRING, 0),
+  ASN1_IMP(CMS_OriginatorIdentifierOrKey, d.originatorKey, CMS_OriginatorPublicKey, 1)
+} ASN1_CHOICE_END(CMS_OriginatorIdentifierOrKey)
+
+ASN1_SEQUENCE(CMS_KeyAgreeRecipientInfo) = {
+       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(CMS_KEKIdentifier) = {
+       ASN1_SIMPLE(CMS_KEKIdentifier, keyIdentifier, ASN1_OCTET_STRING),
+       ASN1_OPT(CMS_KEKIdentifier, date, ASN1_GENERALIZEDTIME),
+       ASN1_OPT(CMS_KEKIdentifier, other, CMS_OtherKeyAttribute)
+} ASN1_SEQUENCE_END(CMS_KEKIdentifier)
+
+ASN1_SEQUENCE(CMS_KEKRecipientInfo) = {
+       ASN1_SIMPLE(CMS_KEKRecipientInfo, version, LONG),
+       ASN1_SIMPLE(CMS_KEKRecipientInfo, kekid, CMS_KEKIdentifier),
+       ASN1_SIMPLE(CMS_KEKRecipientInfo, keyEncryptionAlgorithm, X509_ALGOR),
+       ASN1_SIMPLE(CMS_KEKRecipientInfo, encryptedKey, ASN1_OCTET_STRING)
+} ASN1_SEQUENCE_END(CMS_KEKRecipientInfo)
+
+ASN1_SEQUENCE(CMS_PasswordRecipientInfo) = {
+       ASN1_SIMPLE(CMS_PasswordRecipientInfo, version, LONG),
+       ASN1_IMP_OPT(CMS_PasswordRecipientInfo, keyDerivationAlgorithm, X509_ALGOR, 0),
+       ASN1_SIMPLE(CMS_PasswordRecipientInfo, keyEncryptionAlgorithm, X509_ALGOR),
+       ASN1_SIMPLE(CMS_PasswordRecipientInfo, encryptedKey, ASN1_OCTET_STRING)
+} ASN1_SEQUENCE_END(CMS_PasswordRecipientInfo)
+
+ASN1_SEQUENCE(CMS_OtherRecipientInfo) = {
+  ASN1_SIMPLE(CMS_OtherRecipientInfo, oriType, ASN1_OBJECT),
+  ASN1_OPT(CMS_OtherRecipientInfo, oriValue, ASN1_ANY)
+} ASN1_SEQUENCE_END(CMS_OtherRecipientInfo)
+
+/* Free up RecipientInfo additional data */
+static int cms_ri_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it)
+       {
+       if(operation == ASN1_OP_FREE_PRE)
+               {
+               CMS_RecipientInfo *ri = (CMS_RecipientInfo *)*pval;
+               if (ri->type == CMS_RECIPINFO_TRANS)
+                       {
+                       CMS_KeyTransRecipientInfo *ktri = ri->d.ktri;
+                       if (ktri->pkey)
+                               EVP_PKEY_free(ktri->pkey);
+                       if (ktri->recip)
+                               X509_free(ktri->recip);
+                       }
+               else if (ri->type == CMS_RECIPINFO_KEK)
+                       {
+                       CMS_KEKRecipientInfo *kekri = ri->d.kekri;
+                       if (kekri->key)
+                               {
+                               OPENSSL_cleanse(kekri->key, kekri->keylen);
+                               OPENSSL_free(kekri->key);
+                               }
+                       }
+               }
+       return 1;
+       }
+
+ASN1_CHOICE_cb(CMS_RecipientInfo, cms_ri_cb) = {
+       ASN1_SIMPLE(CMS_RecipientInfo, d.ktri, CMS_KeyTransRecipientInfo),
+       ASN1_IMP(CMS_RecipientInfo, d.kari, CMS_KeyAgreeRecipientInfo, 1),
+       ASN1_IMP(CMS_RecipientInfo, d.kekri, CMS_KEKRecipientInfo, 2),
+       ASN1_IMP(CMS_RecipientInfo, d.pwri, CMS_PasswordRecipientInfo, 3),
+       ASN1_IMP(CMS_RecipientInfo, d.ori, CMS_OtherRecipientInfo, 4)
+} ASN1_CHOICE_END_cb(CMS_RecipientInfo, CMS_RecipientInfo, type)
+
+ASN1_NDEF_SEQUENCE(CMS_EnvelopedData) = {
+       ASN1_SIMPLE(CMS_EnvelopedData, version, LONG),
+       ASN1_IMP_OPT(CMS_EnvelopedData, originatorInfo, CMS_OriginatorInfo, 0),
+       ASN1_SET_OF(CMS_EnvelopedData, recipientInfos, CMS_RecipientInfo),
+       ASN1_SIMPLE(CMS_EnvelopedData, encryptedContentInfo, CMS_EncryptedContentInfo),
+       ASN1_IMP_SET_OF_OPT(CMS_EnvelopedData, unprotectedAttrs, X509_ATTRIBUTE, 1)
+} ASN1_NDEF_SEQUENCE_END(CMS_EnvelopedData)
+
+ASN1_NDEF_SEQUENCE(CMS_DigestedData) = {
+       ASN1_SIMPLE(CMS_DigestedData, version, LONG),
+       ASN1_SIMPLE(CMS_DigestedData, digestAlgorithm, X509_ALGOR),
+       ASN1_SIMPLE(CMS_DigestedData, encapContentInfo, CMS_EncapsulatedContentInfo),
+       ASN1_SIMPLE(CMS_DigestedData, digest, ASN1_OCTET_STRING)
+} ASN1_NDEF_SEQUENCE_END(CMS_DigestedData)
+
+ASN1_NDEF_SEQUENCE(CMS_EncryptedData) = {
+       ASN1_SIMPLE(CMS_EncryptedData, version, LONG),
+       ASN1_SIMPLE(CMS_EncryptedData, encryptedContentInfo, CMS_EncryptedContentInfo),
+       ASN1_IMP_SET_OF_OPT(CMS_EncryptedData, unprotectedAttrs, X509_ATTRIBUTE, 1)
+} ASN1_NDEF_SEQUENCE_END(CMS_EncryptedData)
+
+ASN1_NDEF_SEQUENCE(CMS_AuthenticatedData) = {
+       ASN1_SIMPLE(CMS_AuthenticatedData, version, LONG),
+       ASN1_IMP_OPT(CMS_AuthenticatedData, originatorInfo, CMS_OriginatorInfo, 0),
+       ASN1_SET_OF(CMS_AuthenticatedData, recipientInfos, CMS_RecipientInfo),
+       ASN1_SIMPLE(CMS_AuthenticatedData, macAlgorithm, X509_ALGOR),
+       ASN1_IMP(CMS_AuthenticatedData, digestAlgorithm, X509_ALGOR, 1),
+       ASN1_SIMPLE(CMS_AuthenticatedData, encapContentInfo, CMS_EncapsulatedContentInfo),
+       ASN1_IMP_SET_OF_OPT(CMS_AuthenticatedData, authAttrs, X509_ALGOR, 2),
+       ASN1_SIMPLE(CMS_AuthenticatedData, mac, ASN1_OCTET_STRING),
+       ASN1_IMP_SET_OF_OPT(CMS_AuthenticatedData, unauthAttrs, X509_ALGOR, 3)
+} ASN1_NDEF_SEQUENCE_END(CMS_AuthenticatedData)
+
+ASN1_NDEF_SEQUENCE(CMS_CompressedData) = {
+       ASN1_SIMPLE(CMS_CompressedData, version, LONG),
+       ASN1_SIMPLE(CMS_CompressedData, compressionAlgorithm, X509_ALGOR),
+       ASN1_SIMPLE(CMS_CompressedData, encapContentInfo, CMS_EncapsulatedContentInfo),
+} ASN1_NDEF_SEQUENCE_END(CMS_CompressedData)
+
+/* This is the ANY DEFINED BY table for the top level ContentInfo structure */
+
+ASN1_ADB_TEMPLATE(cms_default) = ASN1_EXP(CMS_ContentInfo, d.other, ASN1_ANY, 0);
+
+ASN1_ADB(CMS_ContentInfo) = {
+       ADB_ENTRY(NID_pkcs7_data, ASN1_NDEF_EXP(CMS_ContentInfo, d.data, ASN1_OCTET_STRING_NDEF, 0)),
+       ADB_ENTRY(NID_pkcs7_signed, ASN1_NDEF_EXP(CMS_ContentInfo, d.signedData, CMS_SignedData, 0)),
+       ADB_ENTRY(NID_pkcs7_enveloped, ASN1_NDEF_EXP(CMS_ContentInfo, d.envelopedData, CMS_EnvelopedData, 0)),
+       ADB_ENTRY(NID_pkcs7_digest, ASN1_NDEF_EXP(CMS_ContentInfo, d.digestedData, CMS_DigestedData, 0)),
+       ADB_ENTRY(NID_pkcs7_encrypted, ASN1_NDEF_EXP(CMS_ContentInfo, d.encryptedData, CMS_EncryptedData, 0)),
+       ADB_ENTRY(NID_id_smime_ct_authData, ASN1_NDEF_EXP(CMS_ContentInfo, d.authenticatedData, CMS_AuthenticatedData, 0)),
+       ADB_ENTRY(NID_id_smime_ct_compressedData, ASN1_NDEF_EXP(CMS_ContentInfo, d.compressedData, CMS_CompressedData, 0)),
+} ASN1_ADB_END(CMS_ContentInfo, 0, contentType, 0, &cms_default_tt, NULL);
+
+ASN1_NDEF_SEQUENCE(CMS_ContentInfo) = {
+       ASN1_SIMPLE(CMS_ContentInfo, contentType, ASN1_OBJECT),
+       ASN1_ADB_OBJECT(CMS_ContentInfo)
+} ASN1_NDEF_SEQUENCE_END(CMS_ContentInfo)
+
+/* Specials for signed attributes */
+
+/* When signing attributes we want to reorder them to match the sorted
+ * encoding.
+ */
+
+ASN1_ITEM_TEMPLATE(CMS_Attributes_Sign) = 
+       ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SET_ORDER, 0, CMS_ATTRIBUTES, X509_ATTRIBUTE)
+ASN1_ITEM_TEMPLATE_END(CMS_Attributes_Sign)
+
+/* When verifying attributes we need to use the received order. So 
+ * we use SEQUENCE OF and tag it to SET OF
+ */
+
+ASN1_ITEM_TEMPLATE(CMS_Attributes_Verify) = 
+       ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF | ASN1_TFLG_IMPTAG | ASN1_TFLG_UNIVERSAL,
+                               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)
+
diff --git a/crypto/openssl-0.9/crypto/cms/cms_att.c b/crypto/openssl-0.9/crypto/cms/cms_att.c
new file mode 100644 (file)
index 0000000..5b71722
--- /dev/null
@@ -0,0 +1,195 @@
+/* crypto/cms/cms_att.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 <openssl/asn1t.h>
+#include <openssl/pem.h>
+#include <openssl/x509v3.h>
+#include <openssl/err.h>
+#include "cms.h"
+#include "cms_lcl.h"
+
+/* CMS SignedData Attribute utilities */
+
+int CMS_signed_get_attr_count(const CMS_SignerInfo *si)
+{
+       return X509at_get_attr_count(si->signedAttrs);
+}
+
+int CMS_signed_get_attr_by_NID(const CMS_SignerInfo *si, int nid,
+                         int lastpos)
+{
+       return X509at_get_attr_by_NID(si->signedAttrs, nid, lastpos);
+}
+
+int CMS_signed_get_attr_by_OBJ(const CMS_SignerInfo *si, ASN1_OBJECT *obj,
+                         int lastpos)
+{
+       return X509at_get_attr_by_OBJ(si->signedAttrs, obj, lastpos);
+}
+
+X509_ATTRIBUTE *CMS_signed_get_attr(const CMS_SignerInfo *si, int loc)
+{
+       return X509at_get_attr(si->signedAttrs, loc);
+}
+
+X509_ATTRIBUTE *CMS_signed_delete_attr(CMS_SignerInfo *si, int loc)
+{
+       return X509at_delete_attr(si->signedAttrs, loc);
+}
+
+int CMS_signed_add1_attr(CMS_SignerInfo *si, X509_ATTRIBUTE *attr)
+{
+       if(X509at_add1_attr(&si->signedAttrs, attr)) return 1;
+       return 0;
+}
+
+int CMS_signed_add1_attr_by_OBJ(CMS_SignerInfo *si,
+                       const ASN1_OBJECT *obj, int type,
+                       const void *bytes, int len)
+{
+       if(X509at_add1_attr_by_OBJ(&si->signedAttrs, obj,
+                               type, bytes, len)) return 1;
+       return 0;
+}
+
+int CMS_signed_add1_attr_by_NID(CMS_SignerInfo *si,
+                       int nid, int type,
+                       const void *bytes, int len)
+{
+       if(X509at_add1_attr_by_NID(&si->signedAttrs, nid,
+                               type, bytes, len)) return 1;
+       return 0;
+}
+
+int CMS_signed_add1_attr_by_txt(CMS_SignerInfo *si,
+                       const char *attrname, int type,
+                       const void *bytes, int len)
+{
+       if(X509at_add1_attr_by_txt(&si->signedAttrs, attrname,
+                               type, bytes, len)) return 1;
+       return 0;
+}
+
+void *CMS_signed_get0_data_by_OBJ(CMS_SignerInfo *si, ASN1_OBJECT *oid,
+                                       int lastpos, int type)
+{
+       return X509at_get0_data_by_OBJ(si->signedAttrs, oid, lastpos, type);
+}
+
+int CMS_unsigned_get_attr_count(const CMS_SignerInfo *si)
+{
+       return X509at_get_attr_count(si->unsignedAttrs);
+}
+
+int CMS_unsigned_get_attr_by_NID(const CMS_SignerInfo *si, int nid,
+                         int lastpos)
+{
+       return X509at_get_attr_by_NID(si->unsignedAttrs, nid, lastpos);
+}
+
+int CMS_unsigned_get_attr_by_OBJ(const CMS_SignerInfo *si, ASN1_OBJECT *obj,
+                         int lastpos)
+{
+       return X509at_get_attr_by_OBJ(si->unsignedAttrs, obj, lastpos);
+}
+
+X509_ATTRIBUTE *CMS_unsigned_get_attr(const CMS_SignerInfo *si, int loc)
+{
+       return X509at_get_attr(si->unsignedAttrs, loc);
+}
+
+X509_ATTRIBUTE *CMS_unsigned_delete_attr(CMS_SignerInfo *si, int loc)
+{
+       return X509at_delete_attr(si->unsignedAttrs, loc);
+}
+
+int CMS_unsigned_add1_attr(CMS_SignerInfo *si, X509_ATTRIBUTE *attr)
+{
+       if(X509at_add1_attr(&si->unsignedAttrs, attr)) return 1;
+       return 0;
+}
+
+int CMS_unsigned_add1_attr_by_OBJ(CMS_SignerInfo *si,
+                       const ASN1_OBJECT *obj, int type,
+                       const void *bytes, int len)
+{
+       if(X509at_add1_attr_by_OBJ(&si->unsignedAttrs, obj,
+                               type, bytes, len)) return 1;
+       return 0;
+}
+
+int CMS_unsigned_add1_attr_by_NID(CMS_SignerInfo *si,
+                       int nid, int type,
+                       const void *bytes, int len)
+{
+       if(X509at_add1_attr_by_NID(&si->unsignedAttrs, nid,
+                               type, bytes, len)) return 1;
+       return 0;
+}
+
+int CMS_unsigned_add1_attr_by_txt(CMS_SignerInfo *si,
+                       const char *attrname, int type,
+                       const void *bytes, int len)
+{
+       if(X509at_add1_attr_by_txt(&si->unsignedAttrs, attrname,
+                               type, bytes, len)) return 1;
+       return 0;
+}
+
+void *CMS_unsigned_get0_data_by_OBJ(CMS_SignerInfo *si, ASN1_OBJECT *oid,
+                                       int lastpos, int type)
+{
+       return X509at_get0_data_by_OBJ(si->unsignedAttrs, oid, lastpos, type);
+}
+
+/* Specific attribute cases */
similarity index 56%
copy from crypto/openssl-0.9/crypto/comp/comp_err.c
copy to crypto/openssl-0.9/crypto/cms/cms_cd.c
index 0737222..a5fc2c4 100644 (file)
@@ -1,6 +1,9 @@
-/* crypto/comp/comp_err.c */
+/* crypto/cms/cms_cd.c */
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
+ * project.
+ */
 /* ====================================================================
- * Copyright (c) 1999-2005 The OpenSSL Project.  All rights reserved.
+ * 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
@@ -22,7 +25,7 @@
  * 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
- *    openssl-core@OpenSSL.org.
+ *    licensing@OpenSSL.org.
  *
  * 5. Products derived from this software may not be called "OpenSSL"
  *    nor may "OpenSSL" appear in their names without prior written
  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
  * OF THE POSSIBILITY OF SUCH DAMAGE.
  * ====================================================================
- *
- * This product includes cryptographic software written by Eric Young
- * (eay@cryptsoft.com).  This product includes software written by Tim
- * Hudson (tjh@cryptsoft.com).
- *
  */
 
-/* NOTE: this file was auto generated by the mkerr.pl script: any changes
- * made to it will be overwritten when the script next updates this file,
- * only reason strings will be preserved.
- */
-
-#include <stdio.h>
+#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/bio.h>
 #include <openssl/comp.h>
+#include "cms_lcl.h"
 
-/* BEGIN ERROR CODES */
-#ifndef OPENSSL_NO_ERR
+DECLARE_ASN1_ITEM(CMS_CompressedData)
 
-#define ERR_FUNC(func) ERR_PACK(ERR_LIB_COMP,func,0)
-#define ERR_REASON(reason) ERR_PACK(ERR_LIB_COMP,0,reason)
+#ifdef ZLIB
 
-static ERR_STRING_DATA COMP_str_functs[]=
-       {
-{0,NULL}
-       };
+/* CMS CompressedData Utilities */
 
-static ERR_STRING_DATA COMP_str_reasons[]=
+CMS_ContentInfo *cms_CompressedData_create(int comp_nid)
        {
-{0,NULL}
-       };
+       CMS_ContentInfo *cms;
+       CMS_CompressedData *cd;
+       /* Will need something cleverer if there is ever more than one
+        * compression algorithm or parameters have some meaning...
+        */
+       if (comp_nid != NID_zlib_compression)
+               {
+               CMSerr(CMS_F_CMS_COMPRESSEDDATA_CREATE,
+                               CMS_R_UNSUPPORTED_COMPRESSION_ALGORITHM);
+               return NULL;
+               }
+       cms = CMS_ContentInfo_new();
+       if (!cms)
+               return NULL;
 
-#endif
+       cd = M_ASN1_new_of(CMS_CompressedData);
 
-void ERR_load_COMP_strings(void)
-       {
-#ifndef OPENSSL_NO_ERR
+       if (!cd)
+               goto err;
+
+       cms->contentType = OBJ_nid2obj(NID_id_smime_ct_compressedData);
+       cms->d.compressedData = cd;
+
+       cd->version = 0;
+
+       X509_ALGOR_set0(cd->compressionAlgorithm,
+                       OBJ_nid2obj(NID_zlib_compression),
+                       V_ASN1_UNDEF, NULL);
 
-       if (ERR_func_error_string(COMP_str_functs[0].error) == NULL)
+       cd->encapContentInfo->eContentType = OBJ_nid2obj(NID_pkcs7_data);
+
+       return cms;
+
+       err:
+
+       if (cms)
+