Updates from 0.9.8-stable
authorDr. Stephen Henson <steve@openssl.org>
Fri, 14 Dec 2007 01:16:16 +0000 (01:16 +0000)
committerDr. Stephen Henson <steve@openssl.org>
Fri, 14 Dec 2007 01:16:16 +0000 (01:16 +0000)
98 files changed:
CHANGES
Configure
apps/apps.h
apps/ec.c
apps/ocsp.c
apps/pkcs12.c
apps/s_apps.h
apps/s_cb.c
apps/s_client.c
apps/s_server.c
apps/speed.c
apps/x509.c
crypto/asn1/asn1.h
crypto/asn1/t_req.c
crypto/asn1/tasn_dec.c
crypto/asn1/tasn_enc.c
crypto/asn1/x_crl.c
crypto/asn1/x_exten.c
crypto/bn/asm/ia64.S
crypto/conf/conf_api.c
crypto/conf/conf_mod.c
crypto/dh/dh_check.c
crypto/ec/ec.h
crypto/ec/ec_err.c
crypto/ec/ec_mult.c
crypto/ec/ectest.c
crypto/ecdsa/ecs_ossl.c
crypto/engine/eng_table.c
crypto/evp/evp.h
crypto/ex_data.c
crypto/md4/md4test.c
crypto/md5/md5test.c
crypto/objects/obj_dat.h
crypto/objects/obj_mac.h
crypto/objects/obj_mac.num
crypto/objects/objects.txt
crypto/ocsp/ocsp.h
crypto/ocsp/ocsp_err.c
crypto/ocsp/ocsp_ht.c
crypto/opensslv.h
crypto/ossl_typ.h
crypto/pem/pem.h
crypto/rand/rand_lib.c
crypto/ripemd/rmdtest.c
crypto/sha/asm/sha1-x86_64.pl
crypto/sha/sha1test.c
crypto/stack/safestack.h
crypto/x509/x509.h
crypto/x509/x509_vfy.c
crypto/x509/x509_vpm.c
crypto/x509v3/pcy_tree.c
crypto/x509v3/v3_utl.c
crypto/x509v3/x509v3.h
doc/apps/s_client.pod
doc/apps/s_server.pod
doc/crypto/ASN1_generate_nconf.pod
doc/crypto/DH_set_method.pod
doc/crypto/DSA_set_method.pod
doc/crypto/OPENSSL_ia32cap.pod
doc/crypto/RAND_bytes.pod
doc/crypto/RAND_set_rand_method.pod
doc/crypto/RSA_set_method.pod
doc/crypto/X509_NAME_print_ex.pod
doc/crypto/engine.pod
doc/ssl/SSL_CTX_set_options.pod
e_os.h
engines/e_gmp.c
engines/e_ubsec.c
makevms.com
ssl/d1_both.c
ssl/d1_clnt.c
ssl/d1_lib.c
ssl/d1_pkt.c
ssl/d1_srvr.c
ssl/dtls1.h
ssl/s23_clnt.c
ssl/s2_clnt.c
ssl/s2_srvr.c
ssl/s3_clnt.c
ssl/s3_lib.c
ssl/s3_srvr.c
ssl/ssl.h
ssl/ssl3.h
ssl/ssl_asn1.c
ssl/ssl_cert.c
ssl/ssl_err.c
ssl/ssl_lib.c
ssl/ssl_locl.h
ssl/ssl_sess.c
ssl/ssl_txt.c
ssl/t1_enc.c
ssl/t1_lib.c
ssl/tls1.h
util/clean-depend.pl
util/mk1mf.pl
util/mkdef.pl
util/opensslwrap.sh
util/ssleay.num

diff --git a/CHANGES b/CHANGES
index 7b7c9ac8768681ee0c8c76a2766e4b6d5d1b7338..dba53baca8db9ae8d089c4875b183c405b4c5131 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -2,8 +2,7 @@
  OpenSSL CHANGES
  _______________
 
- Changes between 0.9.8e and 0.9.8f-fips  [xx XXX xxxx]
-
+ Changes between 0.9.8g and 0.9.8h-fips  [xx XXX xxxx]
 
   *) Add option --with-fipslibdir to specify location of fipscanister.lib
      and friends. When combined with fips build option fipscanister.lib is
      Update Windows build system.
      [Steve Henson]
 
+ Changes between 0.9.8g and 0.9.8h  [xx XXX xxxx]
+
+  *) 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:
+     + Binary incompatibility of ssl_ctx_st structure
+     + DTLS interoperation with non-compliant servers
+     + Don't call get_session_cb() without proposed session
+     + Fix ia64 assembler code
+     [Andy Polyakov, Steve Henson]
+
+ Changes between 0.9.8e and 0.9.8f  [11 Oct 2007]
+
+  *) DTLS Handshake overhaul. There were longstanding issues with
+     OpenSSL DTLS implementation, which were making it impossible for
+     RFC 4347 compliant client to communicate with OpenSSL server.
+     Unfortunately just fixing these incompatibilities would "cut off"
+     pre-0.9.8f clients. To allow for hassle free upgrade post-0.9.8e
+     server keeps tolerating non RFC compliant syntax. The opposite is
+     not true, 0.9.8f client can not communicate with earlier server.
+     This update even addresses CVE-2007-4995.
+     [Andy Polyakov]
+
+  *) Changes to avoid need for function casts in OpenSSL: some compilers
+     (gcc 4.2 and later) reject their use.
+     [Kurt Roeckx <kurt@roeckx.be>, Peter Hartley <pdh@utter.chaos.org.uk>,
+      Steve Henson]
+  
+  *) Add RFC4507 support to OpenSSL. This includes the corrections in
+     RFC4507bis. The encrypted ticket format is an encrypted encoded
+     SSL_SESSION structure, that way new session features are automatically
+     supported.
+
+     If a client application caches session in an SSL_SESSION structure
+     support is transparent because tickets are now stored in the encoded
+     SSL_SESSION.
+     
+     The SSL_CTX structure automatically generates keys for ticket
+     protection in servers so again support should be possible
+     with no application modification.
+
+     If a client or server wishes to disable RFC4507 support then the option
+     SSL_OP_NO_TICKET can be set.
+
+     Add a TLS extension debugging callback to allow the contents of any client
+     or server extensions to be examined.
+
+     This work was sponsored by Google.
+     [Steve Henson]
+
+  *) Add initial support for TLS extensions, specifically for the server_name
+     extension so far.  The SSL_SESSION, SSL_CTX, and SSL data structures now
+     have new members for a host name.  The SSL data structure has an
+     additional member SSL_CTX *initial_ctx so that new sessions can be
+     stored in that context to allow for session resumption, even after the
+     SSL has been switched to a new SSL_CTX in reaction to a client's
+     server_name extension.
+
+     New functions (subject to change):
+
+         SSL_get_servername()
+         SSL_get_servername_type()
+         SSL_set_SSL_CTX()
+
+     New CTRL codes and macros (subject to change):
+
+         SSL_CTRL_SET_TLSEXT_SERVERNAME_CB
+                                 - SSL_CTX_set_tlsext_servername_callback()
+         SSL_CTRL_SET_TLSEXT_SERVERNAME_ARG
+                                      - SSL_CTX_set_tlsext_servername_arg()
+         SSL_CTRL_SET_TLSEXT_HOSTNAME           - SSL_set_tlsext_host_name()
+
+     openssl s_client has a new '-servername ...' option.
+
+     openssl s_server has new options '-servername_host ...', '-cert2 ...',
+     '-key2 ...', '-servername_fatal' (subject to change).  This allows
+     testing the HostName extension for a specific single host name ('-cert'
+     and '-key' remain fallbacks for handshakes without HostName
+     negotiation).  If the unrecogninzed_name alert has to be sent, this by
+     default is a warning; it becomes fatal with the '-servername_fatal'
+     option.
+
+     [Peter Sylvester,  Remy Allais, Christophe Renou, Steve Henson]
+
+  *) Add AES and SSE2 assembly language support to VC++ build.
+     [Steve Henson]
+
+  *) Mitigate attack on final subtraction in Montgomery reduction.
+     [Andy Polyakov]
+
+  *) Fix crypto/ec/ec_mult.c to work properly with scalars of value 0
+     (which previously caused an internal error).
+     [Bodo Moeller]
+
+  *) Squeeze another 10% out of IGE mode when in != out.
+     [Ben Laurie]
+
+  *) AES IGE mode speedup.
+     [Dean Gaudet (Google)]
+
+  *) Add the Korean symmetric 128-bit cipher SEED (see
+     http://www.kisa.or.kr/kisa/seed/jsp/seed_eng.jsp) and
+     add SEED ciphersuites from RFC 4162:
+
+        TLS_RSA_WITH_SEED_CBC_SHA      =  "SEED-SHA"
+        TLS_DHE_DSS_WITH_SEED_CBC_SHA  =  "DHE-DSS-SEED-SHA"
+        TLS_DHE_RSA_WITH_SEED_CBC_SHA  =  "DHE-RSA-SEED-SHA"
+        TLS_DH_anon_WITH_SEED_CBC_SHA  =  "ADH-SEED-SHA"
+
+     To minimize changes between patchlevels in the OpenSSL 0.9.8
+     series, SEED remains excluded from compilation unless OpenSSL
+     is configured with 'enable-seed'.
+     [KISA, Bodo Moeller]
+
+  *) Mitigate branch prediction attacks, which can be practical if a
+     single processor is shared, allowing a spy process to extract
+     information.  For detailed background information, see
+     http://eprint.iacr.org/2007/039 (O. Aciicmez, S. Gueron,
+     J.-P. Seifert, "New Branch Prediction Vulnerabilities in OpenSSL
+     and Necessary Software Countermeasures").  The core of the change
+     are new versions BN_div_no_branch() and
+     BN_mod_inverse_no_branch() of BN_div() and BN_mod_inverse(),
+     respectively, which are slower, but avoid the security-relevant
+     conditional branches.  These are automatically called by BN_div()
+     and BN_mod_inverse() if the flag BN_FLG_CONSTTIME is set for one
+     of the input BIGNUMs.  Also, BN_is_bit_set() has been changed to
+     remove a conditional branch.
+
+     BN_FLG_CONSTTIME is the new name for the previous
+     BN_FLG_EXP_CONSTTIME flag, since it now affects more than just
+     modular exponentiation.  (Since OpenSSL 0.9.7h, setting this flag
+     in the exponent causes BN_mod_exp_mont() to use the alternative
+     implementation in BN_mod_exp_mont_consttime().)  The old name
+     remains as a deprecated alias.
+
+     Similary, RSA_FLAG_NO_EXP_CONSTTIME is replaced by a more general
+     RSA_FLAG_NO_CONSTTIME flag since the RSA implementation now uses
+     constant-time implementations for more than just exponentiation.
+     Here too the old name is kept as a deprecated alias.
+
+     BN_BLINDING_new() will now use BN_dup() for the modulus so that
+     the BN_BLINDING structure gets an independent copy of the
+     modulus.  This means that the previous "BIGNUM *m" argument to
+     BN_BLINDING_new() and to BN_BLINDING_create_param() now
+     essentially becomes "const BIGNUM *m", although we can't actually
+     change this in the header file before 0.9.9.  It allows
+     RSA_setup_blinding() to use BN_with_flags() on the modulus to
+     enable BN_FLG_CONSTTIME.
+
+     [Matthew D Wood (Intel Corp)]
+
+  *) In the SSL/TLS server implementation, be strict about session ID
+     context matching (which matters if an application uses a single
+     external cache for different purposes).  Previously,
+     out-of-context reuse was forbidden only if SSL_VERIFY_PEER was
+     set.  This did ensure strict client verification, but meant that,
+     with applications using a single external cache for quite
+     different requirements, clients could circumvent ciphersuite
+     restrictions for a given session ID context by starting a session
+     in a different context.
+     [Bodo Moeller]
+
+  *) Include "!eNULL" in SSL_DEFAULT_CIPHER_LIST to make sure that
+     a ciphersuite string such as "DEFAULT:RSA" cannot enable
+     authentication-only ciphersuites.
+     [Bodo Moeller]
+
  Changes between 0.9.8e and 0.9.8f  [23 Feb 2007]
 
   *) Mitigate branch prediction attacks, which can be practical if a
index c63c0c71cb57ed4c445ec50bb39eb17684ee8c9e..042bfcefda947e984b90119899cd0a30f8300fe7 100755 (executable)
--- a/Configure
+++ b/Configure
@@ -619,6 +619,7 @@ my %disabled = ( # "what"         => "comment"
                  "rfc3779"        => "default",
                  "seed"           => "default",
                  "shared"         => "default",
+                 "tlsext"         => "default",
                  "zlib"           => "default",
                  "zlib-dynamic"   => "default"
                );
@@ -882,6 +883,10 @@ if (defined($disabled{"md5"}) || defined($disabled{"sha"})
        $disabled{"tls1"} = "forced";
        }
 
+if (defined($disabled{"tls1"}))
+       {
+       $disabled{"tlsext"} = "forced";
+       }
 
 if ($target eq "TABLE") {
        foreach $target (sort keys %table) {
index 945ef9d9eb7765dfa986a26f7e40f78d14888322..c1ce1bc90ccda8c8cfbb285263ba9684a918b60f 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);
@@ -231,6 +234,12 @@ extern int in_FIPS_mode;
 #  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;
@@ -278,6 +287,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 c63437fe2acd566b3b1766aad63225cdb1f57325..771e15f3577c176031a24f5f5c6581802071082e 100644 (file)
--- a/apps/ec.c
+++ b/apps/ec.c
@@ -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 3dc36c4bdc4a4ab67b5a6f68f1e780fd487123af..b95424b69bfd02dde1fbb4198fbd37caf641d289 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/e_os2.h>
+#include <openssl/bio.h>
 #include <openssl/ocsp.h>
-#include <openssl/err.h>
+#include <openssl/txt_db.h>
 #include <openssl/ssl.h>
-#include <openssl/bn.h>
+#include "apps.h"
 
 /* Maximum leeway in validity period: default 5 minutes */
 #define MAX_VALIDITY_PERIOD    (5 * 60)
@@ -86,6 +87,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 +115,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 +157,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 +722,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 +878,6 @@ end:
                OPENSSL_free(host);
                OPENSSL_free(port);
                OPENSSL_free(path);
-               SSL_CTX_free(ctx);
                }
 
        OPENSSL_EXIT(ret);
@@ -1121,6 +1101,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 +1212,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 77e9d7ba733fe655ef5f4a1dbe5d5227d6a01b3c..77907116fa23118fb7af2bb13fbb34b772f891ca 100644 (file)
@@ -484,7 +484,7 @@ int MAIN(int argc, char **argv)
                                        X509_keyid_set1(ucert, NULL, 0);
                                        X509_alias_set1(ucert, NULL, 0);
                                        /* Remove from list */
-                                       sk_X509_delete(certs, i);
+                                       (void)sk_X509_delete(certs, i);
                                        break;
                                        }
                                }
index 886a95a2b8ceb061c365b3b751ab153da8d7a4e7..08fbbc2229640f3eb6d4e15af90f7e64926a4970 100644 (file)
@@ -167,4 +167,7 @@ long MS_CALLBACK bio_dump_callback(BIO *bio, int cmd, const char *argp,
 #ifdef HEADER_SSL_H
 void MS_CALLBACK apps_ssl_info_callback(const SSL *s, int where, int ret);
 void MS_CALLBACK msg_cb(int write_p, int version, int content_type, const void *buf, size_t len, SSL *ssl, void *arg);
+void MS_CALLBACK tlsext_cb(SSL *s, int client_server, int type,
+                                       unsigned char *data, int len,
+                                       void *arg);
 #endif
index b4992aa623511445b951e7db28f79d521cb1c7c0..a512589e8c87d92b80fdc84751d02b7e9f91923c 100644 (file)
@@ -575,3 +575,62 @@ void MS_CALLBACK msg_cb(int write_p, int version, int content_type, const void *
                }
        (void)BIO_flush(bio);
        }
+
+void MS_CALLBACK tlsext_cb(SSL *s, int client_server, int type,
+                                       unsigned char *data, int len,
+                                       void *arg)
+       {
+       BIO *bio = arg;
+       char *extname;
+
+       switch(type)
+               {
+               case TLSEXT_TYPE_server_name:
+               extname = "server name";
+               break;
+
+               case TLSEXT_TYPE_max_fragment_length:
+               extname = "max fragment length";
+               break;
+
+               case TLSEXT_TYPE_client_certificate_url:
+               extname = "client certificate URL";
+               break;
+
+               case TLSEXT_TYPE_trusted_ca_keys:
+               extname = "trusted CA keys";
+               break;
+
+               case TLSEXT_TYPE_truncated_hmac:
+               extname = "truncated HMAC";
+               break;
+
+               case TLSEXT_TYPE_status_request:
+               extname = "status request";
+               break;
+
+               case TLSEXT_TYPE_elliptic_curves:
+               extname = "elliptic curves";
+               break;
+
+               case TLSEXT_TYPE_ec_point_formats:
+               extname = "EC point formats";
+               break;
+
+               case TLSEXT_TYPE_session_ticket:
+               extname = "server ticket";
+               break;
+
+
+               default:
+               extname = "unknown";
+               break;
+
+               }
+       
+       BIO_printf(bio, "TLS %s extension \"%s\" (id=%d), len=%d\n",
+                       client_server ? "server": "client",
+                       extname, type, len);
+       BIO_dump(bio, (char *)data, len);
+       (void)BIO_flush(bio);
+       }
index 6df534fa7ac428bf20ed5c341bfaa09aad77417a..a4983c178fcfc43151e70b23ce0c37c8bb366033 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"
 
@@ -171,11 +172,18 @@ static int c_nbio=0;
 #endif
 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;
@@ -231,9 +239,37 @@ static void sc_usage(void)
        BIO_printf(bio_err," -engine id    - Initialise and use the specified engine\n");
 #endif
        BIO_printf(bio_err," -rand file%cfile%c...\n", LIST_SEPARATOR_CHAR, LIST_SEPARATOR_CHAR);
-
+       BIO_printf(bio_err," -sess_out arg - file to write SSL session to\n");
+       BIO_printf(bio_err," -sess_in arg  - file to read SSL session from\n");
+#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
        }
 
+#ifndef OPENSSL_NO_TLSEXT
+
+/* This is a context that we pass to callbacks */
+typedef struct tlsextctx_st {
+   BIO * biodebug;
+   int ack;
+} tlsextctx;
+
+
+static int MS_CALLBACK ssl_servername_cb(SSL *s, int *ad, void *arg)
+       {
+       tlsextctx * p = (tlsextctx *) arg;
+       const char * hn= SSL_get_servername(s, TLSEXT_NAMETYPE_host_name);
+       if (SSL_get_servername_type(s) != -1) 
+               p->ack = !SSL_session_reused(s) && hn != NULL;
+       else 
+               BIO_printf(bio_err,"Can't use SSL_get_servername\n");
+       
+       return SSL_TLSEXT_ERR_OK;
+       }
+#endif
 enum
 {
        PROTO_OFF       = 0,
@@ -287,6 +323,13 @@ int MAIN(int argc, char **argv)
        struct timeval tv;
 #endif
 
+#ifndef OPENSSL_NO_TLSEXT
+       char *servername = NULL; 
+        tlsextctx tlsextcbp = 
+        {NULL,0};
+#endif
+       char *sess_in = NULL;
+       char *sess_out = NULL;
        struct sockaddr peer;
        int peerlen = sizeof(peer);
        int enable_timeouts = 0 ;
@@ -361,6 +404,16 @@ int MAIN(int argc, char **argv)
                        if (--argc < 1) goto bad;
                        cert_file= *(++argv);
                        }
+               else if (strcmp(*argv,"-sess_out") == 0)
+                       {
+                       if (--argc < 1) goto bad;
+                       sess_out = *(++argv);
+                       }
+               else if (strcmp(*argv,"-sess_in") == 0)
+                       {
+                       if (--argc < 1) goto bad;
+                       sess_in = *(++argv);
+                       }
                else if (strcmp(*argv,"-certform") == 0)
                        {
                        if (--argc < 1) goto bad;
@@ -385,6 +438,12 @@ int MAIN(int argc, char **argv)
                        c_Pause=1;
                else if (strcmp(*argv,"-debug") == 0)
                        c_debug=1;
+#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)
                        dbug_init();
@@ -460,6 +519,10 @@ int MAIN(int argc, char **argv)
                        off|=SSL_OP_NO_SSLv3;
                else if (strcmp(*argv,"-no_ssl2") == 0)
                        off|=SSL_OP_NO_SSLv2;
+#ifndef OPENSSL_NO_TLSEXT
+               else if (strcmp(*argv,"-no_ticket") == 0)
+                       { off|=SSL_OP_NO_TICKET; }
+#endif
                else if (strcmp(*argv,"-serverpref") == 0)
                        off|=SSL_OP_CIPHER_SERVER_PREFERENCE;
                else if (strcmp(*argv,"-cipher") == 0)
@@ -498,6 +561,14 @@ int MAIN(int argc, char **argv)
                        if (--argc < 1) goto bad;
                        inrand= *(++argv);
                        }
+#ifndef OPENSSL_NO_TLSEXT
+               else if (strcmp(*argv,"-servername") == 0)
+                       {
+                       if (--argc < 1) goto bad;
+                       servername= *(++argv);
+                       /* meth=TLSv1_client_method(); */
+                       }
+#endif
                else
                        {
                        BIO_printf(bio_err,"unknown option %s\n",*argv);
@@ -621,8 +692,51 @@ bad:
 
        store = SSL_CTX_get_cert_store(ctx);
        X509_STORE_set_flags(store, vflags);
+#ifndef OPENSSL_NO_TLSEXT
+       if (servername != NULL)
+               {
+               tlsextcbp.biodebug = bio_err;
+               SSL_CTX_set_tlsext_servername_callback(ctx, ssl_servername_cb);
+               SSL_CTX_set_tlsext_servername_arg(ctx, &tlsextcbp);
+               }
+#endif
 
        con=SSL_new(ctx);
+       if (sess_in)
+               {
+               SSL_SESSION *sess;
+               BIO *stmp = BIO_new_file(sess_in, "r");
+               if (!stmp)
+                       {
+                       BIO_printf(bio_err, "Can't open session file %s\n",
+                                               sess_in);
+                       ERR_print_errors(bio_err);
+                       goto end;
+                       }
+               sess = PEM_read_bio_SSL_SESSION(stmp, NULL, 0, NULL);
+               BIO_free(stmp);
+               if (!sess)
+                       {
+                       BIO_printf(bio_err, "Can't open session file %s\n",
+                                               sess_in);
+                       ERR_print_errors(bio_err);
+                       goto end;
+                       }
+               SSL_set_session(con, sess);
+               SSL_SESSION_free(sess);
+               }
+#ifndef OPENSSL_NO_TLSEXT
+       if (servername != NULL)
+               {
+               if (!SSL_set_tlsext_host_name(con,servername))
+                       {
+                       BIO_printf(bio_err,"Unable to set TLS servername extension.\n");
+                       ERR_print_errors(bio_err);
+                       goto end;
+                       }
+               }
+#endif
+
 #ifndef OPENSSL_NO_KRB5
        if (con  &&  (con->kssl_ctx = kssl_ctx_new()) != NULL)
                 {
@@ -714,6 +828,30 @@ re_start:
                SSL_set_msg_callback(con, msg_cb);
                SSL_set_msg_callback_arg(con, bio_c_out);
                }
+#ifndef OPENSSL_NO_TLSEXT
+       if (c_tlsextdebug)
+               {
+               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);
        SSL_set_connect_state(con);
@@ -837,6 +975,17 @@ re_start:
                        if (in_init)
                                {
                                in_init=0;
+                               if (sess_out)
+                                       {
+                                       BIO *stmp = BIO_new_file(sess_out, "w");
+                                       if (stmp)
+                                               {
+                                               PEM_write_bio_SSL_SESSION(stmp, SSL_get_session(con));
+                                               BIO_free(stmp);
+                                               }
+                                       else 
+                                               BIO_printf(bio_err, "Error writing session file %s\n", sess_out);
+                                       }
                                print_stuff(bio_c_out,con,full_log);
                                if (full_log > 0) full_log--;
 
@@ -1306,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 6c433e63fd647a4c2a457ed7dd47622b8c5fe6ab..2b4e256c1a46d890886e5ffb3e7c3d7f3f646894 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
@@ -238,6 +239,9 @@ static int bufsize=BUFSIZZ;
 static int accept_socket= -1;
 
 #define TEST_CERT      "server.pem"
+#ifndef OPENSSL_NO_TLSEXT
+#define TEST_CERT2     "server2.pem"
+#endif
 #undef PROG
 #define PROG           s_server_main
 
@@ -247,6 +251,9 @@ static char *cipher=NULL;
 static int s_server_verify=SSL_VERIFY_NONE;
 static int s_server_session_id_context = 1; /* anything will do */
 static const char *s_cert_file=TEST_CERT,*s_key_file=NULL;
+#ifndef OPENSSL_NO_TLSEXT
+static const char *s_cert_file2=TEST_CERT2,*s_key_file2=NULL;
+#endif
 static char *s_dcert_file=NULL,*s_dkey_file=NULL;
 #ifdef FIONBIO
 static int s_nbio=0;
@@ -254,10 +261,18 @@ static int s_nbio=0;
 static int s_nbio_test=0;
 int s_crlf=0;
 static SSL_CTX *ctx=NULL;
+#ifndef OPENSSL_NO_TLSEXT
+static SSL_CTX *ctx2=NULL;
+#endif
 static int www=0;
 
 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;
 
@@ -285,6 +300,11 @@ static void s_server_init(void)
        s_dkey_file=NULL;
        s_cert_file=TEST_CERT;
        s_key_file=NULL;
+#ifndef OPENSSL_NO_TLSEXT
+       s_cert_file2=TEST_CERT2;
+       s_key_file2=NULL;
+       ctx2=NULL;
+#endif
 #ifdef FIONBIO
        s_nbio=0;
 #endif
@@ -371,6 +391,16 @@ static void sv_usage(void)
 #endif
        BIO_printf(bio_err," -id_prefix arg - Generate SSL/TLS session IDs prefixed by 'arg'\n");
        BIO_printf(bio_err," -rand file%cfile%c...\n", LIST_SEPARATOR_CHAR, LIST_SEPARATOR_CHAR);
+#ifndef OPENSSL_NO_TLSEXT
+       BIO_printf(bio_err," -servername host - servername for HostName TLS extension\n");
+       BIO_printf(bio_err," -servername_fatal - on mismatch send fatal alert (default warning alert)\n");
+       BIO_printf(bio_err," -cert2 arg    - certificate file to use for servername\n");
+       BIO_printf(bio_err,"                 (default is %s)\n",TEST_CERT2);
+       BIO_printf(bio_err," -key2 arg     - Private Key file to use for servername, in cert file if\n");
+       BIO_printf(bio_err,"                 not specified (default is %s)\n",TEST_CERT2);
+       BIO_printf(bio_err," -tlsextdebug  - hex dump of all TLS extensions received\n");
+       BIO_printf(bio_err," -no_ticket    - disable use of RFC4507bis session tickets\n");
+#endif
        }
 
 static int local_argc=0;
@@ -526,6 +556,185 @@ static int ebcdic_puts(BIO *bp, const char *str)
 }
 #endif
 
+#ifndef OPENSSL_NO_TLSEXT
+
+/* This is a context that we pass to callbacks */
+typedef struct tlsextctx_st {
+   char * servername;
+   BIO * biodebug;
+   int extension_error;
+} tlsextctx;
+
+
+static int MS_CALLBACK ssl_servername_cb(SSL *s, int *ad, void *arg)
+       {
+       tlsextctx * p = (tlsextctx *) arg;
+       const char * servername = SSL_get_servername(s, TLSEXT_NAMETYPE_host_name);
+        if (servername && p->biodebug) 
+               BIO_printf(p->biodebug,"Hostname in TLS extension: \"%s\"\n",servername);
+        
+       if (!p->servername)
+               return SSL_TLSEXT_ERR_NOACK;
+       
+       if (servername)
+               {
+               if (strcmp(servername,p->servername)) 
+                       return p->extension_error;
+               if (ctx2)
+                       {
+                       BIO_printf(p->biodebug,"Swiching server context.\n");
+                       SSL_set_SSL_CTX(s,ctx2);
+                       }     
+               }
+       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 **);
 
 int MAIN(int argc, char *argv[])
@@ -545,10 +754,7 @@ int MAIN(int argc, char *argv[])
        int no_tmp_rsa=0,no_dhe=0,no_ecdhe=0,nocert=0;
        int state=0;
        SSL_METHOD *meth=NULL;
-#ifdef sock_type
-#undef sock_type
-#endif
-    int sock_type=SOCK_STREAM;
+        int socket_type=SOCK_STREAM;
 #ifndef OPENSSL_NO_ENGINE
        ENGINE *e=NULL;
 #endif
@@ -559,6 +765,14 @@ int MAIN(int argc, char *argv[])
        int s_dcert_format = FORMAT_PEM, s_dkey_format = FORMAT_PEM;
        X509 *s_cert = NULL, *s_dcert = NULL;
        EVP_PKEY *s_key = NULL, *s_dkey = NULL;
+#ifndef OPENSSL_NO_TLSEXT
+       EVP_PKEY *s_key2 = NULL;
+       X509 *s_cert2 = NULL;
+#endif
+
+#ifndef OPENSSL_NO_TLSEXT
+        tlsextctx tlsextcbp = {NULL, NULL, SSL_TLSEXT_ERR_ALERT_WARNING};
+#endif
 
 #if !defined(OPENSSL_NO_SSL2) && !defined(OPENSSL_NO_SSL3)
        meth=SSLv23_server_method();
@@ -724,6 +938,37 @@ int MAIN(int argc, char *argv[])
                        }
                else if (strcmp(*argv,"-debug") == 0)
                        { s_debug=1; }
+#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; }
                else if (strcmp(*argv,"-hack") == 0)
@@ -754,6 +999,10 @@ int MAIN(int argc, char *argv[])
                        { off|=SSL_OP_NO_SSLv3; }
                else if (strcmp(*argv,"-no_tls1") == 0)
                        { off|=SSL_OP_NO_TLSv1; }
+#ifndef OPENSSL_NO_TLSEXT
+               else if (strcmp(*argv,"-no_ticket") == 0)
+                       { off|=SSL_OP_NO_TICKET; }
+#endif
 #ifndef OPENSSL_NO_SSL2
                else if (strcmp(*argv,"-ssl2") == 0)
                        { meth=SSLv2_server_method(); }
@@ -770,7 +1019,7 @@ int MAIN(int argc, char *argv[])
                else if (strcmp(*argv,"-dtls1") == 0)
                        { 
                        meth=DTLSv1_server_method();
-                       sock_type = SOCK_DGRAM;
+                       socket_type = SOCK_DGRAM;
                        }
                else if (strcmp(*argv,"-timeout") == 0)
                        enable_timeouts = 1;
@@ -799,6 +1048,25 @@ int MAIN(int argc, char *argv[])
                        if (--argc < 1) goto bad;
                        inrand= *(++argv);
                        }
+#ifndef OPENSSL_NO_TLSEXT
+               else if (strcmp(*argv,"-servername") == 0)
+                       {
+                       if (--argc < 1) goto bad;
+                       tlsextcbp.servername= *(++argv);
+                       }
+               else if (strcmp(*argv,"-servername_fatal") == 0)
+                       { tlsextcbp.extension_error = SSL_TLSEXT_ERR_ALERT_FATAL; }
+               else if (strcmp(*argv,"-cert2") == 0)
+                       {
+                       if (--argc < 1) goto bad;
+                       s_cert_file2= *(++argv);
+                       }
+               else if (strcmp(*argv,"-key2") == 0)
+                       {
+                       if (--argc < 1) goto bad;
+                       s_key_file2= *(++argv);
+                       }
+#endif
                else
                        {
                        BIO_printf(bio_err,"unknown option %s\n",*argv);
@@ -831,6 +1099,10 @@ bad:
 
        if (s_key_file == NULL)
                s_key_file = s_cert_file;
+#ifndef OPENSSL_NO_TLSEXT
+       if (s_key_file2 == NULL)
+               s_key_file2 = s_cert_file2;
+#endif
 
        if (nocert == 0)
                {
@@ -850,8 +1122,29 @@ bad:
                        ERR_print_errors(bio_err);
                        goto end;
                        }
-               }
 
+#ifndef OPENSSL_NO_TLSEXT
+               if (tlsextcbp.servername) 
+                       {
+                       s_key2 = load_key(bio_err, s_key_file2, s_key_format, 0, pass, e,
+                               "second server certificate private key file");
+                       if (!s_key2)
+                               {
+                               ERR_print_errors(bio_err);
+                               goto end;
+                               }
+                       
+                       s_cert2 = load_cert(bio_err,s_cert_file2,s_cert_format,
+                               NULL, e, "second server certificate file");
+                       
+                       if (!s_cert2)
+                               {
+                               ERR_print_errors(bio_err);
+                               goto end;
+                               }
+                       }
+#endif
+               }
        if (s_dcert_file)
                {
 
@@ -908,6 +1201,10 @@ bad:
                s_key_file=NULL;
                s_dcert_file=NULL;
                s_dkey_file=NULL;
+#ifndef OPENSSL_NO_TLSEXT
+               s_cert_file2=NULL;
+               s_key_file2=NULL;
+#endif
                }
 
        ctx=SSL_CTX_new(meth);
@@ -939,7 +1236,7 @@ bad:
        /* DTLS: partial reads end up discarding unread UDP bytes :-( 
         * Setting read ahead solves this problem.
         */
-       if (sock_type == SOCK_DGRAM) SSL_CTX_set_read_ahead(ctx, 1);
+       if (socket_type == SOCK_DGRAM) SSL_CTX_set_read_ahead(ctx, 1);
 
        if (state) SSL_CTX_set_info_callback(ctx,apps_ssl_info_callback);
 
@@ -966,6 +1263,62 @@ bad:
                }
        store = SSL_CTX_get_cert_store(ctx);
        X509_STORE_set_flags(store, vflags);
+#ifndef OPENSSL_NO_TLSEXT
+       if (s_cert2)
+               {
+               ctx2=SSL_CTX_new(meth);
+               if (ctx2 == NULL)
+                       {
+                       ERR_print_errors(bio_err);
+                       goto end;
+                       }
+               }
+       
+       if (ctx2)
+               {
+               BIO_printf(bio_s_out,"Setting secondary ctx parameters\n");
+
+               if (session_id_prefix)
+                       {
+                       if(strlen(session_id_prefix) >= 32)
+                               BIO_printf(bio_err,
+                                       "warning: id_prefix is too long, only one new session will be possible\n");
+                       else if(strlen(session_id_prefix) >= 16)
+                               BIO_printf(bio_err,
+                                       "warning: id_prefix is too long if you use SSLv2\n");
+                       if(!SSL_CTX_set_generate_session_id(ctx2, generate_session_id))
+                               {
+                               BIO_printf(bio_err,"error setting 'id_prefix'\n");
+                               ERR_print_errors(bio_err);
+                               goto end;
+                               }
+                       BIO_printf(bio_err,"id_prefix '%s' set.\n", session_id_prefix);
+                       }
+               SSL_CTX_set_quiet_shutdown(ctx2,1);
+               if (bugs) SSL_CTX_set_options(ctx2,SSL_OP_ALL);
+               if (hack) SSL_CTX_set_options(ctx2,SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG);
+               SSL_CTX_set_options(ctx2,off);
+
+               /* DTLS: partial reads end up discarding unread UDP bytes :-( 
+                * Setting read ahead solves this problem.
+                */
+               if (socket_type == SOCK_DGRAM) SSL_CTX_set_read_ahead(ctx2, 1);
+
+
+               if (state) SSL_CTX_set_info_callback(ctx2,apps_ssl_info_callback);
+
+               SSL_CTX_sess_set_cache_size(ctx2,128);
+
+               if ((!SSL_CTX_load_verify_locations(ctx2,CAfile,CApath)) ||
+                       (!SSL_CTX_set_default_verify_paths(ctx2)))
+                       {
+                       ERR_print_errors(bio_err);
+                       }
+               store = SSL_CTX_get_cert_store(ctx2);
+               X509_STORE_set_flags(store, vflags);
+               }
+#endif 
+
 
 #ifndef OPENSSL_NO_DH
        if (!no_dhe)
@@ -989,6 +1342,24 @@ bad:
                (void)BIO_flush(bio_s_out);
 
                SSL_CTX_set_tmp_dh(ctx,dh);
+#ifndef OPENSSL_NO_TLSEXT
+               if (ctx2)
+                       {
+                       if (!dhfile)
+                               { 
+                               DH *dh2=load_dh_param(s_cert_file2);
+                               if (dh2 != NULL)
+                                       {
+                                       BIO_printf(bio_s_out,"Setting temp DH parameters\n");
+                                       (void)BIO_flush(bio_s_out);
+
+                                       DH_free(dh);
+                                       dh = dh2;
+                                       }
+                               }
+                       SSL_CTX_set_tmp_dh(ctx2,dh);
+                       }
+#endif
                DH_free(dh);
                }
 #endif
@@ -1034,12 +1405,20 @@ bad:
                (void)BIO_flush(bio_s_out);
 
                SSL_CTX_set_tmp_ecdh(ctx,ecdh);
+#ifndef OPENSSL_NO_TLSEXT
+               if (ctx2) 
+                       SSL_CTX_set_tmp_ecdh(ctx2,ecdh);
+#endif
                EC_KEY_free(ecdh);
                }
 #endif
        
        if (!set_cert_key_stuff(ctx,s_cert,s_key))
                goto end;
+#ifndef OPENSSL_NO_TLSEXT
+       if (ctx2 && !set_cert_key_stuff(ctx2,s_cert2,s_key2))
+               goto end; 
+#endif
        if (s_dcert != NULL)
                {
                if (!set_cert_key_stuff(ctx,s_dcert,s_dkey))
@@ -1049,7 +1428,13 @@ bad:
 #ifndef OPENSSL_NO_RSA
 #if 1
        if (!no_tmp_rsa)
+               {
                SSL_CTX_set_tmp_rsa_callback(ctx,tmp_rsa_cb);
+#ifndef OPENSSL_NO_TLSEXT
+               if (ctx2) 
+                       SSL_CTX_set_tmp_rsa_callback(ctx2,tmp_rsa_cb);
+#endif 
+               }
 #else
        if (!no_tmp_rsa && SSL_CTX_need_tmp_RSA(ctx))
                {
@@ -1065,6 +1450,16 @@ bad:
                        ERR_print_errors(bio_err);
                        goto end;
                        }
+#ifndef OPENSSL_NO_TLSEXT
+                       if (ctx2)
+                               {
+                               if (!SSL_CTX_set_tmp_rsa(ctx2,rsa))
+                                       {
+                                       ERR_print_errors(bio_err);
+                                       goto end;
+                                       }
+                               }
+#endif
                RSA_free(rsa);
                BIO_printf(bio_s_out,"\n");
                }
@@ -1076,19 +1471,46 @@ bad:
                BIO_printf(bio_err,"error setting cipher list\n");
                ERR_print_errors(bio_err);
                goto end;
+#ifndef OPENSSL_NO_TLSEXT
+               if (ctx2 && !SSL_CTX_set_cipher_list(ctx2,cipher))
+                       {
+                       BIO_printf(bio_err,"error setting cipher list\n");
+                       ERR_print_errors(bio_err);
+                       goto end;
+                       }
+#endif
        }
        SSL_CTX_set_verify(ctx,s_server_verify,verify_callback);
        SSL_CTX_set_session_id_context(ctx,(void*)&s_server_session_id_context,
                sizeof s_server_session_id_context);
 
+#ifndef OPENSSL_NO_TLSEXT
+       if (ctx2)
+               {
+               SSL_CTX_set_verify(ctx2,s_server_verify,verify_callback);
+               SSL_CTX_set_session_id_context(ctx2,(void*)&s_server_session_id_context,
+                       sizeof s_server_session_id_context);
+
+               tlsextcbp.biodebug = bio_s_out;
+               SSL_CTX_set_tlsext_servername_callback(ctx2, ssl_servername_cb);
+               SSL_CTX_set_tlsext_servername_arg(ctx2, &tlsextcbp);
+               SSL_CTX_set_tlsext_servername_callback(ctx, ssl_servername_cb);
+               SSL_CTX_set_tlsext_servername_arg(ctx, &tlsextcbp);
+               }
+#endif
        if (CAfile != NULL)
-           SSL_CTX_set_client_CA_list(ctx,SSL_load_client_CA_file(CAfile));
-
+               {
+               SSL_CTX_set_client_CA_list(ctx,SSL_load_client_CA_file(CAfile));
+#ifndef OPENSSL_NO_TLSEXT
+               if (ctx2) 
+                       SSL_CTX_set_client_CA_list(ctx2,SSL_load_client_CA_file(CAfile));
+#endif
+               }
        BIO_printf(bio_s_out,"ACCEPT\n");
        if (www)
-               do_server(port,sock_type,&accept_socket,www_body, context);
+               do_server(port,socket_type,&accept_socket,www_body, context);
        else
-               do_server(port,sock_type,&accept_socket,sv_body, context);
+               do_server(port,socket_type,&accept_socket,sv_body, context);
        print_stats(bio_s_out,ctx);
        ret=0;
 end:
@@ -1105,6 +1527,13 @@ end:
                OPENSSL_free(pass);
        if (dpass)
                OPENSSL_free(dpass);
+#ifndef OPENSSL_NO_TLSEXT
+       if (ctx2 != NULL) SSL_CTX_free(ctx2);
+       if (s_cert2)
+               X509_free(s_cert2);
+       if (s_key2)
+               EVP_PKEY_free(s_key2);
+#endif
        if (bio_s_out != NULL)
                {
         BIO_free(bio_s_out);
@@ -1171,6 +1600,19 @@ static int sv_body(char *hostname, int s, unsigned char *context)
 
        if (con == NULL) {
                con=SSL_new(ctx);
+#ifndef OPENSSL_NO_TLSEXT
+       if (s_tlsextdebug)
+               {
+               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)
                         {
@@ -1241,6 +1683,13 @@ static int sv_body(char *hostname, int s, unsigned char *context)
                SSL_set_msg_callback(con, msg_cb);
                SSL_set_msg_callback_arg(con, bio_s_out);
                }
+#ifndef OPENSSL_NO_TLSEXT
+       if (s_tlsextdebug)
+               {
+               SSL_set_tlsext_debug_callback(con, tlsext_cb);
+               SSL_set_tlsext_debug_arg(con, bio_s_out);
+               }
+#endif
 
        width=s+1;
        for (;;)
@@ -1606,6 +2055,13 @@ static int www_body(char *hostname, int s, unsigned char *context)
        if (!BIO_set_write_buffer_size(io,bufsize)) goto err;
 
        if ((con=SSL_new(ctx)) == NULL) goto err;
+#ifndef OPENSSL_NO_TLSEXT
+               if (s_tlsextdebug)
+                       {
+                       SSL_set_tlsext_debug_callback(con, tlsext_cb);
+                       SSL_set_tlsext_debug_arg(con, bio_s_out);
+                       }
+#endif
 #ifndef OPENSSL_NO_KRB5
        if ((con->kssl_ctx = kssl_ctx_new()) != NULL)
                {
index 85f559ed81e45dca03443bfffd6d5f72cddfc36b..8a1974f5fe9b89519cc3a5d673fe03cd34ba7d32 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 5f61eb5c467a54d125ba42a65ae0cd7d78bc0f4e..f6938356f8a7acd5f0b655ab24788588fb39e1e8 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 30f1eecd5b90bb47ecea31573be97a20bdbe6643..f15131ea3e1c89c13cb226179fd4c702e7260687 100644 (file)
@@ -322,6 +322,17 @@ typedef struct ASN1_VALUE_st ASN1_VALUE;
 #define I2D_OF(type) int (*)(type *,unsigned char **)
 #define I2D_OF_const(type) int (*)(const type *,unsigned char **)
 
+#define CHECKED_D2I_OF(type, d2i) \
+    ((d2i_of_void*) (1 ? d2i : ((D2I_OF(type))0)))
+#define CHECKED_I2D_OF(type, i2d) \
+    ((i2d_of_void*) (1 ? i2d : ((I2D_OF(type))0)))
+#define CHECKED_NEW_OF(type, xnew) \
+    ((void *(*)(void)) (1 ? xnew : ((type *(*)(void))0)))
+#define CHECKED_PTR_OF(type, p) \
+    ((void*) (1 ? p : (type*)0))
+#define CHECKED_PPTR_OF(type, p) \
+    ((void**) (1 ? p : (type**)0))
+
 #define TYPEDEF_D2I_OF(type) typedef type *d2i_of_##type(type **,const unsigned char **,long)
 #define TYPEDEF_I2D_OF(type) typedef int i2d_of_##type(type *,unsigned char **)
 #define TYPEDEF_D2I2D_OF(type) TYPEDEF_D2I_OF(type); TYPEDEF_I2D_OF(type)
@@ -902,23 +913,41 @@ int ASN1_object_size(int constructed, int length, int tag);
 
 /* Used to implement other functions */
 void *ASN1_dup(i2d_of_void *i2d, d2i_of_void *d2i, char *x);
+
 #define ASN1_dup_of(type,i2d,d2i,x) \
-       ((type *(*)(I2D_OF(type),D2I_OF(type),type *))openssl_fcast(ASN1_dup))(i2d,d2i,x)
+    ((type*)ASN1_dup(CHECKED_I2D_OF(type, i2d), \
+                    CHECKED_D2I_OF(type, d2i), \
+                    CHECKED_PTR_OF(type, x)))
+
 #define ASN1_dup_of_const(type,i2d,d2i,x) \
-       ((type *(*)(I2D_OF_const(type),D2I_OF(type),type *))openssl_fcast(ASN1_dup))(i2d,d2i,x)
+    ((type*)ASN1_dup(CHECKED_I2D_OF(const type, i2d), \
+                    CHECKED_D2I_OF(type, d2i), \
+                    CHECKED_PTR_OF(const type, x)))
 
 void *ASN1_item_dup(const ASN1_ITEM *it, void *x);
 
 #ifndef OPENSSL_NO_FP_API
 void *ASN1_d2i_fp(void *(*xnew)(void), d2i_of_void *d2i, FILE *in, void **x);
+
 #define ASN1_d2i_fp_of(type,xnew,d2i,in,x) \
-       ((type *(*)(type *(*)(void),D2I_OF(type),FILE *,type **))openssl_fcast(ASN1_d2i_fp))(xnew,d2i,in,x)
+    ((type*)ASN1_d2i_fp(CHECKED_NEW_OF(type, xnew), \
+                       CHECKED_D2I_OF(type, d2i), \
+                       in, \
+                       CHECKED_PPTR_OF(type, x)))
+
 void *ASN1_item_d2i_fp(const ASN1_ITEM *it, FILE *in, void *x);
 int ASN1_i2d_fp(i2d_of_void *i2d,FILE *out,void *x);
+
 #define ASN1_i2d_fp_of(type,i2d,out,x) \
-       ((int (*)(I2D_OF(type),FILE *,type *))openssl_fcast(ASN1_i2d_fp))(i2d,out,x)
+    (ASN1_i2d_fp(CHECKED_I2D_OF(type, i2d), \
+                out, \
+                CHECKED_PTR_OF(type, x)))
+
 #define ASN1_i2d_fp_of_const(type,i2d,out,x) \
-       ((int (*)(I2D_OF_const(type),FILE *,type *))openssl_fcast(ASN1_i2d_fp))(i2d,out,x)
+    (ASN1_i2d_fp(CHECKED_I2D_OF(const type, i2d), \
+                out, \
+                CHECKED_PTR_OF(const type, x)))
+
 int ASN1_item_i2d_fp(const ASN1_ITEM *it, FILE *out, void *x);
 int ASN1_STRING_print_ex_fp(FILE *fp, ASN1_STRING *str, unsigned long flags);
 #endif
@@ -927,14 +956,26 @@ int ASN1_STRING_to_UTF8(unsigned char **out, ASN1_STRING *in);
 
 #ifndef OPENSSL_NO_BIO
 void *ASN1_d2i_bio(void *(*xnew)(void), d2i_of_void *d2i, BIO *in, void **x);
+
 #define ASN1_d2i_bio_of(type,xnew,d2i,in,x) \
-       ((type *(*)(type *(*)(void),D2I_OF(type),BIO *,type **))openssl_fcast(ASN1_d2i_bio))(xnew,d2i,in,x)
+    ((type*)ASN1_d2i_bio( CHECKED_NEW_OF(type, xnew), \
+                         CHECKED_D2I_OF(type, d2i), \
+                         in, \
+                         CHECKED_PPTR_OF(type, x)))
+
 void *ASN1_item_d2i_bio(const ASN1_ITEM *it, BIO *in, void *x);
 int ASN1_i2d_bio(i2d_of_void *i2d,BIO *out, unsigned char *x);
+
 #define ASN1_i2d_bio_of(type,i2d,out,x) \
-       ((int (*)(I2D_OF(type),BIO *,type *))openssl_fcast(ASN1_i2d_bio))(i2d,out,x)
+    (ASN1_i2d_bio(CHECKED_I2D_OF(type, i2d), \
+                 out, \
+                 CHECKED_PTR_OF(type, x)))
+
 #define ASN1_i2d_bio_of_const(type,i2d,out,x) \
-       ((int (*)(I2D_OF_const(type),BIO *,const type *))openssl_fcast(ASN1_i2d_bio))(i2d,out,x)
+    (ASN1_i2d_bio(CHECKED_I2D_OF(const type, i2d), \
+                 out, \
+                 CHECKED_PTR_OF(const type, x)))
+
 int ASN1_item_i2d_bio(const ASN1_ITEM *it, BIO *out, void *x);
 int ASN1_UTCTIME_print(BIO *fp,ASN1_UTCTIME *a);
 int ASN1_GENERALIZEDTIME_print(BIO *fp,ASN1_GENERALIZEDTIME *a);
@@ -977,8 +1018,12 @@ void *ASN1_unpack_string(ASN1_STRING *oct, d2i_of_void *d2i);
 void *ASN1_item_unpack(ASN1_STRING *oct, const ASN1_ITEM *it);
 ASN1_STRING *ASN1_pack_string(void *obj, i2d_of_void *i2d,
                              ASN1_OCTET_STRING **oct);
+
 #define ASN1_pack_string_of(type,obj,i2d,oct) \
-       ((ASN1_STRING *(*)(type *,I2D_OF(type),ASN1_OCTET_STRING **))openssl_fcast(ASN1_pack_string))(obj,i2d,oct)
+    (ASN1_pack_string(CHECKED_PTR_OF(type, obj), \
+                     CHECKED_I2D_OF(type, i2d), \
+                     oct))
+
 ASN1_STRING *ASN1_item_pack(void *obj, const ASN1_ITEM *it, ASN1_OCTET_STRING **oct);
 
 void ASN1_STRING_set_default_mask(unsigned long mask);
index c779a9bb18050bc5fcfc85d1e0ff8820e9477a42..5557e0658448b8009970cbc1ff89331650654613 100644 (file)
@@ -244,7 +244,7 @@ get_next:
                                }
                        }
                }
-       if(!(cflag & X509_FLAG_NO_ATTRIBUTES))
+       if(!(cflag & X509_FLAG_NO_EXTENSIONS))
                {
                exts = X509_REQ_get_extensions(x);
                if(exts)
@@ -262,7 +262,7 @@ get_next:
                                j=X509_EXTENSION_get_critical(ex);
                                if (BIO_printf(bp,": %s\n",j?"critical":"") <= 0)
                                        goto err;
-                               if(!X509V3_EXT_print(bp, ex, 0, 16))
+                               if(!X509V3_EXT_print(bp, ex, cflag, 16))
                                        {
                                        BIO_printf(bp, "%16s", "");
                                        M_ASN1_OCTET_STRING_print(bp,ex->value);
index 66d229b08b39bae6fc34d42eae013a6eb0a8fab4..c4a3abe4f62743b479e3ec2b9813bb47902257b5 100644 (file)
@@ -130,7 +130,7 @@ ASN1_VALUE *ASN1_item_d2i(ASN1_VALUE **pval,
        ASN1_VALUE *ptmpval = NULL;
        if (!pval)
                pval = &ptmpval;
-       asn1_tlc_clear(&c);
+       c.valid = 0;
        if (ASN1_item_ex_d2i(pval, in, len, it, -1, 0, 0, &c) > 0) 
                return *pval;
        return NULL;
@@ -140,7 +140,7 @@ int ASN1_template_d2i(ASN1_VALUE **pval,
                const unsigned char **in, long len, const ASN1_TEMPLATE *tt)
        {
        ASN1_TLC c;
-       asn1_tlc_clear(&c);
+       c.valid = 0;
        return asn1_template_ex_d2i(pval, in, len, tt, 0, &c);
        }
 
index 25c94aa1d95a078c3db63a94ad793cc040d0b128..ed892e2cb2f58e86653b50d6ce9aaa95cc46688b 100644 (file)
@@ -494,7 +494,7 @@ static int asn1_set_seq_out(STACK_OF(ASN1_VALUE) *sk, unsigned char **out,
                {
                for (i = 0, tder = derlst; i < sk_ASN1_VALUE_num(sk);
                                                        i++, tder++)
-                       sk_ASN1_VALUE_set(sk, i, tder->field);
+                       (void)sk_ASN1_VALUE_set(sk, i, tder->field);
                }
        OPENSSL_free(derlst);
        OPENSSL_free(tmpdat);
index b99f8fc522c1e2a6b25f72a61b3ffb0cf3a67ecb..70d56a67f26a28a116fe912887f7d02ec3512c73 100644 (file)
@@ -84,7 +84,7 @@ static int crl_inf_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it)
                 * would affect the output of X509_CRL_print().
                 */
                case ASN1_OP_D2I_POST:
-               sk_X509_REVOKED_set_cmp_func(a->revoked,X509_REVOKED_cmp);
+               (void)sk_X509_REVOKED_set_cmp_func(a->revoked,X509_REVOKED_cmp);
                break;
        }
        return 1;
index 702421b6c851d1ff2b108f15dc86a357b599882e..1732e667125c50ffa3f3a5ce1e677263cb2c4a87 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 7b82b820e62aacdc51278b1d3774314c8b4592d3..951abc53ea5bbae8e308643147fcaa26182e560b 100644 (file)
 .skip  32      // makes the loop body aligned at 64-byte boundary
 bn_add_words:
        .prologue
-       .fframe 0
        .save   ar.pfs,r2
 { .mii;        alloc           r2=ar.pfs,4,12,0,16
        cmp4.le         p6,p0=r35,r0    };;
 { .mfb;        mov             r8=r0                   // return value
 (p6)   br.ret.spnt.many        b0      };;
 
-       .save   ar.lc,r3
 { .mib;        sub             r10=r35,r0,1
+       .save   ar.lc,r3
        mov             r3=ar.lc
        brp.loop.imp    .L_bn_add_words_ctop,.L_bn_add_words_cend-16
                                        }
-       .body
 { .mib;        ADDP            r14=0,r32               // rp
+       .save   pr,r9
        mov             r9=pr           };;
+       .body
 { .mii;        ADDP            r15=0,r33               // ap
        mov             ar.lc=r10
        mov             ar.ec=6         }
@@ -224,21 +224,21 @@ bn_add_words:
 .skip  32      // makes the loop body aligned at 64-byte boundary
 bn_sub_words:
        .prologue
-       .fframe 0
        .save   ar.pfs,r2
 { .mii;        alloc           r2=ar.pfs,4,12,0,16
        cmp4.le         p6,p0=r35,r0    };;
 { .mfb;        mov             r8=r0                   // return value
 (p6)   br.ret.spnt.many        b0      };;
 
-       .save   ar.lc,r3
 { .mib;        sub             r10=r35,r0,1
+       .save   ar.lc,r3
        mov             r3=ar.lc
        brp.loop.imp    .L_bn_sub_words_ctop,.L_bn_sub_words_cend-16
                                        }
-       .body
 { .mib;        ADDP            r14=0,r32               // rp
+       .save   pr,r9
        mov             r9=pr           };;
+       .body
 { .mii;        ADDP            r15=0,r33               // ap
        mov             ar.lc=r10
        mov             ar.ec=6         }
@@ -283,7 +283,6 @@ bn_sub_words:
 .skip  32      // makes the loop body aligned at 64-byte boundary
 bn_mul_words:
        .prologue
-       .fframe 0
        .save   ar.pfs,r2
 #ifdef XMA_TEMPTATION
 { .mfi;        alloc           r2=ar.pfs,4,0,0,0       };;
@@ -294,9 +293,10 @@ bn_mul_words:
        cmp4.le         p6,p0=r34,r0
 (p6)   br.ret.spnt.many        b0              };;
 
-       .save   ar.lc,r3
 { .mii;        sub     r10=r34,r0,1
+       .save   ar.lc,r3
        mov     r3=ar.lc
+       .save   pr,r9
        mov     r9=pr                   };;
 
        .body
@@ -397,22 +397,21 @@ bn_mul_words:
 .skip  48      // makes the loop body aligned at 64-byte boundary
 bn_mul_add_words:
        .prologue
-       .fframe 0
        .save   ar.pfs,r2
-       .save   ar.lc,r3
-       .save   pr,r9
 { .mmi;        alloc           r2=ar.pfs,4,4,0,8
        cmp4.le         p6,p0=r34,r0
+       .save   ar.lc,r3
        mov             r3=ar.lc        };;
 { .mib;        mov             r8=r0           // return value
        sub             r10=r34,r0,1
 (p6)   br.ret.spnt.many        b0      };;
 
-       .body
 { .mib;        setf.sig        f8=r35          // w
+       .save   pr,r9
        mov             r9=pr
        brp.loop.imp    .L_bn_mul_add_words_ctop,.L_bn_mul_add_words_cend-16
                                        }
+       .body
 { .mmi;        ADDP            r14=0,r32       // rp
        ADDP            r15=0,r33       // ap
        mov             ar.lc=r10       }
@@ -466,7 +465,6 @@ bn_mul_add_words:
 .skip  32      // makes the loop body aligned at 64-byte boundary 
 bn_sqr_words:
        .prologue
-       .fframe 0
        .save   ar.pfs,r2
 { .mii;        alloc           r2=ar.pfs,3,0,0,0
        sxt4            r34=r34         };;
@@ -476,9 +474,10 @@ bn_sqr_words:
        nop.f           0x0
 (p6)   br.ret.spnt.many        b0      };;
 
-       .save   ar.lc,r3
 { .mii;        sub     r10=r34,r0,1
+       .save   ar.lc,r3
        mov     r3=ar.lc
+       .save   pr,r9
        mov     r9=pr                   };;
 
        .body
@@ -545,7 +544,6 @@ bn_sqr_words:
 .align 64
 bn_sqr_comba8:
        .prologue
-       .fframe 0
        .save   ar.pfs,r2
 #if defined(_HPUX_SOURCE) && !defined(_LP64)
 { .mii;        alloc   r2=ar.pfs,2,1,0,0
@@ -617,7 +615,6 @@ bn_sqr_comba8:
 .align 64
 bn_mul_comba8:
        .prologue
-       .fframe 0
        .save   ar.pfs,r2
 #if defined(_HPUX_SOURCE) && !defined(_LP64)
 { .mii;        alloc   r2=ar.pfs,3,0,0,0
@@ -1175,7 +1172,6 @@ bn_mul_comba8:
 .align 64
 bn_sqr_comba4:
        .prologue
-       .fframe 0
        .save   ar.pfs,r2
 #if defined(_HPUX_SOURCE) && !defined(_LP64)
 { .mii;        alloc   r2=ar.pfs,2,1,0,0
@@ -1208,7 +1204,6 @@ bn_sqr_comba4:
 .align 64
 bn_mul_comba4:
        .prologue
-       .fframe 0
        .save   ar.pfs,r2
 #if defined(_HPUX_SOURCE) && !defined(_LP64)
 { .mii;        alloc   r2=ar.pfs,3,0,0,0
@@ -1411,11 +1406,11 @@ equ=p24
 .align 64
 bn_div_words:
        .prologue
-       .fframe 0
        .save   ar.pfs,r2
-       .save   b0,r3
 { .mii;        alloc           r2=ar.pfs,3,5,0,8
+       .save   b0,r3
        mov             r3=b0
+       .save   pr,r10
        mov             r10=pr          };;
 { .mmb;        cmp.eq          p6,p0=r34,r0
        mov             r8=-1
index 0032baa7119b2e250ec08b4bbc0db66a4b2cce8d..909d72b4b89af917f02cf17fa2f438c3adedff4d 100644 (file)
@@ -121,7 +121,7 @@ int _CONF_add_string(CONF *conf, CONF_VALUE *section, CONF_VALUE *value)
        v = (CONF_VALUE *)lh_insert(conf->data, value);
        if (v != NULL)
                {
-               sk_CONF_VALUE_delete_ptr(ts,v);
+               (void)sk_CONF_VALUE_delete_ptr(ts,v);
                OPENSSL_free(v->name);
                OPENSSL_free(v->value);
                OPENSSL_free(v);
index 1373d46a4ebd11538b5a0ed2a7eaaaa7668b77ca..628e8333a6d60f4d11eba7ef1d803baa4be80917 100644 (file)
@@ -432,7 +432,7 @@ void CONF_modules_unload(int all)
                if (((md->links > 0) || !md->dso) && !all)
                        continue;
                /* Since we're working in reverse this is OK */
-               sk_CONF_MODULE_delete(supported_modules, i);
+               (void)sk_CONF_MODULE_delete(supported_modules, i);
                module_free(md);
                }
        if (sk_CONF_MODULE_num(supported_modules) == 0)
index c053ea2873275f435ec7041b475fef6433e1ef8c..316cb9221dffc6b725fb0f08060be9aab62ed106 100644 (file)
@@ -62,7 +62,7 @@
 #include <openssl/dh.h>
 
 /* Check that p is a safe prime and
- * if g is 2, 3 or 5, check that is is a suitable generator
+ * if g is 2, 3 or 5, check that it is a suitable generator
  * where
  * for 2, p mod 24 == 11
  * for 3, p mod 12 == 5
index 3c96fbd0d86d6ec8f31d42da1c3f73e43445e785..8bc2a235b1a7576bf0cec79362b618599fab8f31 100644 (file)
@@ -471,6 +471,7 @@ void ERR_load_EC_strings(void);
 #define EC_F_EC_POINT_SET_JPROJECTIVE_COORDINATES_GFP   126
 #define EC_F_EC_POINT_SET_TO_INFINITY                   127
 #define EC_F_EC_PRE_COMP_DUP                            207
+#define EC_F_EC_PRE_COMP_NEW                            196
 #define EC_F_EC_WNAF_MUL                                187
 #define EC_F_EC_WNAF_PRECOMPUTE_MULT                    188
 #define EC_F_I2D_ECPARAMETERS                           190
index 7be315bac92670ae500eb7990e6137df4879c03f..d04c8955604e097fd203eba99af56ba0795978d4 100644 (file)
@@ -1,6 +1,6 @@
 /* crypto/ec/ec_err.c */
 /* ====================================================================
- * Copyright (c) 1999-2005 The OpenSSL Project.  All rights reserved.
+ * Copyright (c) 1999-2007 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
@@ -170,6 +170,7 @@ static ERR_STRING_DATA EC_str_functs[]=
 {ERR_FUNC(EC_F_EC_POINT_SET_JPROJECTIVE_COORDINATES_GFP),      "EC_POINT_set_Jprojective_coordinates_GFp"},
 {ERR_FUNC(EC_F_EC_POINT_SET_TO_INFINITY),      "EC_POINT_set_to_infinity"},
 {ERR_FUNC(EC_F_EC_PRE_COMP_DUP),       "EC_PRE_COMP_DUP"},
+{ERR_FUNC(EC_F_EC_PRE_COMP_NEW),       "EC_PRE_COMP_NEW"},
 {ERR_FUNC(EC_F_EC_WNAF_MUL),   "ec_wNAF_mul"},
 {ERR_FUNC(EC_F_EC_WNAF_PRECOMPUTE_MULT),       "ec_wNAF_precompute_mult"},
 {ERR_FUNC(EC_F_I2D_ECPARAMETERS),      "i2d_ECParameters"},
index a045139a0015099360a06b67af6eb142d9ae1498..2ba173ef36422ad1c715fe3ebd5b0dc9b17cb03d 100644 (file)
@@ -3,7 +3,7 @@
  * Originally written by Bodo Moeller and Nils Larsch for the OpenSSL project.
  */
 /* ====================================================================
- * Copyright (c) 1998-2003 The OpenSSL Project.  All rights reserved.
+ * Copyright (c) 1998-2007 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
@@ -104,7 +104,10 @@ static EC_PRE_COMP *ec_pre_comp_new(const EC_GROUP *group)
 
        ret = (EC_PRE_COMP *)OPENSSL_malloc(sizeof(EC_PRE_COMP));
        if (!ret)
+               {
+               ECerr(EC_F_EC_PRE_COMP_NEW, ERR_R_MALLOC_FAILURE);
                return ret;
+               }
        ret->group = group;
        ret->blocksize = 8; /* default */
        ret->numblocks = 0;
@@ -194,6 +197,19 @@ static signed char *compute_wNAF(const BIGNUM *scalar, int w, size_t *ret_len)
        int bit, next_bit, mask;
        size_t len = 0, j;
        
+       if (BN_is_zero(scalar))
+               {
+               r = OPENSSL_malloc(1);
+               if (!r)
+                       {
+                       ECerr(EC_F_COMPUTE_WNAF, ERR_R_MALLOC_FAILURE);
+                       goto err;
+                       }
+               r[0] = 0;
+               *ret_len = 1;
+               return r;
+               }
+               
        if (w <= 0 || w > 7) /* 'signed char' can represent integers with absolute values less than 2^7 */
                {
                ECerr(EC_F_COMPUTE_WNAF, ERR_R_INTERNAL_ERROR);
@@ -212,7 +228,11 @@ static signed char *compute_wNAF(const BIGNUM *scalar, int w, size_t *ret_len)
        r = OPENSSL_malloc(len + 1); /* modified wNAF may be one digit longer than binary representation
                                      * (*ret_len will be set to the actual length, i.e. at most
                                      * BN_num_bits(scalar) + 1) */
-       if (r == NULL) goto err;
+       if (r == NULL)
+               {
+               ECerr(EC_F_COMPUTE_WNAF, ERR_R_MALLOC_FAILURE);
+               goto err;
+               }
 
        if (scalar->d == NULL || scalar->top == 0)
                {
@@ -425,7 +445,10 @@ int ec_wNAF_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar,
        val_sub  = OPENSSL_malloc(totalnum * sizeof val_sub[0]);
                 
        if (!wsize || !wNAF_len || !wNAF || !val_sub)
+               {
+               ECerr(EC_F_EC_WNAF_MUL, ERR_R_MALLOC_FAILURE);
                goto err;
+               }
 
        wNAF[0] = NULL; /* preliminary pivot */
 
@@ -538,6 +561,7 @@ int ec_wNAF_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar,
                                        wNAF[i] = OPENSSL_malloc(wNAF_len[i]);
                                        if (wNAF[i] == NULL)
                                                {
+                                               ECerr(EC_F_EC_WNAF_MUL, ERR_R_MALLOC_FAILURE);
                                                OPENSSL_free(tmp_wNAF);
                                                goto err;
                                                }
@@ -564,7 +588,11 @@ int ec_wNAF_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar,
         * 'val_sub[i]' is a pointer to the subarray for the i-th point,
         * or to a subarray of 'pre_comp->points' if we already have precomputation. */
        val = OPENSSL_malloc((num_val + 1) * sizeof val[0]);
-       if (val == NULL) goto err;
+       if (val == NULL)
+               {
+               ECerr(EC_F_EC_WNAF_MUL, ERR_R_MALLOC_FAILURE);
+               goto err;
+               }
        val[num_val] = NULL; /* pivot element */
 
        /* allocate points for precomputation */
index 9d469f1cfab47ab7e9c077270eaac32e25de6dd2..6148d553f9d5909e3c6973ab6d069091f9deaf2c 100644 (file)
@@ -659,13 +659,15 @@ void prime_field_tests()
        if (!EC_POINT_is_at_infinity(group, R)) ABORT; /* R = P + 2Q */
 
        {
-               const EC_POINT *points[3];
-               const BIGNUM *scalars[3];
+               const EC_POINT *points[4];
+               const BIGNUM *scalars[4];
+               BIGNUM scalar3;
        
                if (EC_POINT_is_at_infinity(group, Q)) ABORT;
                points[0] = Q;
                points[1] = Q;
                points[2] = Q;
+               points[3] = Q;
 
                if (!BN_add(y, z, BN_value_one())) ABORT;
                if (BN_is_odd(y)) ABORT;
@@ -704,10 +706,16 @@ void prime_field_tests()
                scalars[1] = y;
                scalars[2] = z; /* z = -(x+y) */
 
-               if (!EC_POINTs_mul(group, P, NULL, 3, points, scalars, ctx)) ABORT;
+               BN_init(&scalar3);
+               BN_zero(&scalar3);
+               scalars[3] = &scalar3;
+
+               if (!EC_POINTs_mul(group, P, NULL, 4, points, scalars, ctx)) ABORT;
                if (!EC_POINT_is_at_infinity(group, P)) ABORT;
 
                fprintf(stdout, " ok\n\n");
+
+               BN_free(&scalar3);
        }
 
 
index 32d66a97741d43ae11be4088f0a4767e7826cf06..3ead1af94e7351c5e4bf76aefe146e61b1e636a5 100644 (file)
@@ -251,8 +251,16 @@ static ECDSA_SIG *ecdsa_do_sign(const unsigned char *dgst, int dgst_len,
                ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_EC_LIB);
                goto err;
        }
-       if (dgst_len > BN_num_bytes(order))
+       if (8 * dgst_len > BN_num_bits(order))
        {
+               /* XXX
+                * 
+                * Should provide for optional hash truncation:
+                * Keep the BN_num_bits(order) leftmost bits of dgst
+                * (see March 2006 FIPS 186-3 draft, which has a few
+                * confusing errors in this part though)
+                */
+
                ECDSAerr(ECDSA_F_ECDSA_DO_SIGN,
                        ECDSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE);
                goto err;
@@ -376,6 +384,21 @@ static int ecdsa_do_verify(const unsigned char *dgst, int dgst_len,
                ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_EC_LIB);
                goto err;
        }
+       if (8 * dgst_len > BN_num_bits(order))
+       {
+               /* XXX
+                * 
+                * Should provide for optional hash truncation:
+                * Keep the BN_num_bits(order) leftmost bits of dgst
+                * (see March 2006 FIPS 186-3 draft, which has a few
+                * confusing errors in this part though)
+                */
+
+               ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY,
+                       ECDSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE);
+               ret = 0;
+               goto err;
+       }
 
        if (BN_is_zero(sig->r)          || BN_is_negative(sig->r) || 
            BN_ucmp(sig->r, order) >= 0 || BN_is_zero(sig->s)  ||
index a83c3899ee111f02304a9af6bb0263f2a0a3ba8d..0c1656168d50d60ed45a8bfdd6889eb4e089f6f4 100644 (file)
@@ -147,7 +147,7 @@ int engine_table_register(ENGINE_TABLE **table, ENGINE_CLEANUP_CB *cleanup,
                        lh_insert(&(*table)->piles, fnd);
                        }
                /* A registration shouldn't add duplciate entries */
-               sk_ENGINE_delete_ptr(fnd->sk, e);
+               (void)sk_ENGINE_delete_ptr(fnd->sk, e);
                /* if 'setdefault', this ENGINE goes to the head of the list */
                if(!sk_ENGINE_push(fnd->sk, e))
                        goto end;
@@ -178,7 +178,7 @@ static void int_unregister_cb(ENGINE_PILE *pile, ENGINE *e)
        /* Iterate the 'c->sk' stack removing any occurance of 'e' */
        while((n = sk_ENGINE_find(pile->sk, e)) >= 0)
                {
-               sk_ENGINE_delete(pile->sk, n);
+               (void)sk_ENGINE_delete(pile->sk, n);
                /* "touch" this ENGINE_CIPHER */
                pile->uptodate = 1;
                }
index 054902865ba3ac3ddbbe93127be224c432effce6..ed4393d8fb02c58a4db595f8c562237c096759f5 100644 (file)
@@ -1049,6 +1049,7 @@ void ERR_load_EVP_strings(void);
 #define EVP_R_UNSUPPORTED_SALT_TYPE                     126
 #define EVP_R_WRONG_FINAL_BLOCK_LENGTH                  109
 #define EVP_R_WRONG_PUBLIC_KEY_TYPE                     110
+#define EVP_R_SEED_KEY_SETUP_FAILED                     162
 
 #ifdef  __cplusplus
 }
index 8914218fe8f9c00430d9ab66af4be84e11c376d0..3b11e7a55613ce80be92183f298bb1907fed295e 100644 (file)
@@ -354,7 +354,7 @@ static int def_add_index(EX_CLASS_ITEM *item, long argl, void *argp,
                        }
                }
        toret = item->meth_num++;
-       sk_CRYPTO_EX_DATA_FUNCS_set(item->meth, toret, a);
+       (void)sk_CRYPTO_EX_DATA_FUNCS_set(item->meth, toret, a);
 err:
        CRYPTO_w_unlock(CRYPTO_LOCK_EX_DATA);
        return toret;
index 5da53382c9f89ecfdc13a37b266debf2a5ca9854..56591728a1c88c9185f5e5531bdc1c3121841a57 100644 (file)
@@ -97,12 +97,12 @@ static char *pt(unsigned char *md);
 int main(int argc, char *argv[])
        {
        int i,err=0;
-       unsigned char **P,**R;
+       char **P,**R;
        char *p;
        unsigned char md[MD4_DIGEST_LENGTH];
 
-       P=(unsigned char **)test;
-       R=(unsigned char **)ret;
+       P=test;
+       R=ret;
        i=1;
        while (*P != NULL)
                {
index 0628053fa7ce2071f578e66c84666b3945ca548f..2b37190e32b1c45738b017c892c579b03e081f2a 100644 (file)
@@ -97,12 +97,12 @@ static char *pt(unsigned char *md);
 int main(int argc, char *argv[])
        {
        int i,err=0;
-       unsigned char **P,**R;
+       char **P,**R;
        char *p;
        unsigned char md[MD5_DIGEST_LENGTH];
 
-       P=(unsigned char **)test;
-       R=(unsigned char **)ret;
+       P=test;
+       R=ret;
        i=1;
        while (*P != NULL)
                {
index a9528d5392f5c134289666b41a8597687a3e1bef..49dd4c1763a94521aa97b767651bf93e66cc49a4 100644 (file)
  * [including the GNU Public Licence.]
  */
 
-#define NUM_NID 780
-#define NUM_SN 773
-#define NUM_LN 773
-#define NUM_OBJ 729
+#define NUM_NID 786
+#define NUM_SN 779
+#define NUM_LN 779
+#define NUM_OBJ 735
 
-static unsigned char lvalues[5154]={
+static unsigned char lvalues[5204]={
 0x00,                                        /* [  0] OBJ_undef */
 0x2A,0x86,0x48,0x86,0xF7,0x0D,               /* [  1] OBJ_rsadsi */
 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,          /* [  7] OBJ_pkcs */
@@ -797,6 +797,12 @@ static unsigned char lvalues[5154]={
 0x2A,0x83,0x1A,0x8C,0x9A,0x44,0x01,0x04,     /* [5129] OBJ_seed_cbc */
 0x2A,0x83,0x1A,0x8C,0x9A,0x44,0x01,0x06,     /* [5137] OBJ_seed_ofb128 */
 0x2A,0x83,0x1A,0x8C,0x9A,0x44,0x01,0x05,     /* [5145] OBJ_seed_cfb128 */
+0x2B,0x06,0x01,0x05,0x05,0x08,0x01,0x01,     /* [5153] OBJ_hmac_md5 */
+0x2B,0x06,0x01,0x05,0x05,0x08,0x01,0x02,     /* [5161] OBJ_hmac_sha1 */
+0x2A,0x86,0x48,0x86,0xF6,0x7D,0x07,0x42,0x0D,/* [5169] OBJ_id_PasswordBasedMAC */
+0x2A,0x86,0x48,0x86,0xF6,0x7D,0x07,0x42,0x1E,/* [5178] OBJ_id_DHBasedMac */
+0x2B,0x06,0x01,0x05,0x05,0x07,0x04,0x10,     /* [5187] OBJ_id_it_suppLangTags */
+0x2B,0x06,0x01,0x05,0x05,0x07,0x30,0x05,     /* [5195] OBJ_caRepository */
 };
 
 static ASN1_OBJECT nid_objs[NUM_NID]={
@@ -2009,6 +2015,15 @@ static ASN1_OBJECT nid_objs[NUM_NID]={
 {"SEED-CBC","seed-cbc",NID_seed_cbc,8,&(lvalues[5129]),0},
 {"SEED-OFB","seed-ofb",NID_seed_ofb128,8,&(lvalues[5137]),0},
 {"SEED-CFB","seed-cfb",NID_seed_cfb128,8,&(lvalues[5145]),0},
+{"HMAC-MD5","hmac-md5",NID_hmac_md5,8,&(lvalues[5153]),0},
+{"HMAC-SHA1","hmac-sha1",NID_hmac_sha1,8,&(lvalues[5161]),0},
+{"id-PasswordBasedMAC","password based MAC",NID_id_PasswordBasedMAC,9,
+       &(lvalues[5169]),0},
+{"id-DHBasedMac","Diffie-Hellman based MAC",NID_id_DHBasedMac,9,
+       &(lvalues[5178]),0},
+{"id-it-suppLangTags","id-it-suppLangTags",NID_id_it_suppLangTags,8,
+       &(lvalues[5187]),0},
+{"caRepository","CA Repository",NID_caRepository,8,&(lvalues[5195]),0},
 };
 
 static ASN1_OBJECT *sn_objs[NUM_SN]={
@@ -2089,6 +2104,8 @@ static ASN1_OBJECT *sn_objs[NUM_SN]={
 &(nid_objs[67]),/* "DSA-old" */
 &(nid_objs[297]),/* "DVCS" */
 &(nid_objs[99]),/* "GN" */
+&(nid_objs[780]),/* "HMAC-MD5" */
+&(nid_objs[781]),/* "HMAC-SHA1" */
 &(nid_objs[381]),/* "IANA" */
 &(nid_objs[34]),/* "IDEA-CBC" */
 &(nid_objs[35]),/* "IDEA-CFB" */
@@ -2227,6 +2244,7 @@ static ASN1_OBJECT *sn_objs[NUM_SN]={
 &(nid_objs[703]),/* "c2tnb431r1" */
 &(nid_objs[483]),/* "cNAMERecord" */
 &(nid_objs[179]),/* "caIssuers" */
+&(nid_objs[785]),/* "caRepository" */
 &(nid_objs[443]),/* "caseIgnoreIA5StringSyntax" */
 &(nid_objs[152]),/* "certBag" */
 &(nid_objs[677]),/* "certicom-arc" */
@@ -2285,6 +2303,8 @@ static ASN1_OBJECT *sn_objs[NUM_SN]={
 &(nid_objs[473]),/* "homeTelephoneNumber" */
 &(nid_objs[466]),/* "host" */
 &(nid_objs[442]),/* "iA5StringSyntax" */
+&(nid_objs[783]),/* "id-DHBasedMac" */
+&(nid_objs[782]),/* "id-PasswordBasedMAC" */
 &(nid_objs[266]),/* "id-aca" */
 &(nid_objs[355]),/* "id-aca-accessIdentity" */
 &(nid_objs[354]),/* "id-aca-authenticationInfo" */
@@ -2343,6 +2363,7 @@ static ASN1_OBJECT *sn_objs[NUM_SN]={
 &(nid_objs[299]),/* "id-it-signKeyPairTypes" */
 &(nid_objs[305]),/* "id-it-subscriptionRequest" */
 &(nid_objs[306]),/* "id-it-subscriptionResponse" */
+&(nid_objs[784]),/* "id-it-suppLangTags" */
 &(nid_objs[304]),/* "id-it-unsupportedOIDs" */
 &(nid_objs[128]),/* "id-kp" */
 &(nid_objs[280]),/* "id-mod-attribute-cert" */
@@ -2796,7 +2817,9 @@ static ASN1_OBJECT *ln_objs[NUM_LN]={
 &(nid_objs[365]),/* "Basic OCSP Response" */
 &(nid_objs[285]),/* "Biometric Info" */
 &(nid_objs[179]),/* "CA Issuers" */
+&(nid_objs[785]),/* "CA Repository" */
 &(nid_objs[131]),/* "Code Signing" */
+&(nid_objs[783]),/* "Diffie-Hellman based MAC" */
 &(nid_objs[382]),/* "Directory" */
 &(nid_objs[392]),/* "Domain" */
 &(nid_objs[132]),/* "E-mail Protection" */
@@ -3049,6 +3072,8 @@ static ASN1_OBJECT *ln_objs[NUM_LN]={
 &(nid_objs[509]),/* "generationQualifier" */
 &(nid_objs[601]),/* "generic cryptogram" */
 &(nid_objs[99]),/* "givenName" */
+&(nid_objs[780]),/* "hmac-md5" */
+&(nid_objs[781]),/* "hmac-sha1" */
 &(nid_objs[163]),/* "hmacWithSHA1" */
 &(nid_objs[486]),/* "homePostalAddress" */
 &(nid_objs[473]),/* "homeTelephoneNumber" */
@@ -3113,6 +3138,7 @@ static ASN1_OBJECT *ln_objs[NUM_LN]={
 &(nid_objs[299]),/* "id-it-signKeyPairTypes" */
 &(nid_objs[305]),/* "id-it-subscriptionRequest" */
 &(nid_objs[306]),/* "id-it-subscriptionResponse" */
+&(nid_objs[784]),/* "id-it-suppLangTags" */
 &(nid_objs[304]),/* "id-it-unsupportedOIDs" */
 &(nid_objs[128]),/* "id-kp" */
 &(nid_objs[280]),/* "id-mod-attribute-cert" */
@@ -3272,6 +3298,7 @@ static ASN1_OBJECT *ln_objs[NUM_LN]={
 &(nid_objs[18]),/* "organizationalUnitName" */
 &(nid_objs[475]),/* "otherMailbox" */
 &(nid_objs[489]),/* "pagerTelephoneNumber" */
+&(nid_objs[782]),/* "password based MAC" */
 &(nid_objs[374]),/* "path" */
 &(nid_objs[621]),/* "payment gateway capabilities" */
 &(nid_objs[ 9]),/* "pbeWithMD2AndDES-CBC" */
@@ -3987,6 +4014,7 @@ static ASN1_OBJECT *obj_objs[NUM_OBJ]={
 &(nid_objs[310]),/* OBJ_id_it_implicitConfirm        1 3 6 1 5 5 7 4 13 */
 &(nid_objs[311]),/* OBJ_id_it_confirmWaitTime        1 3 6 1 5 5 7 4 14 */
 &(nid_objs[312]),/* OBJ_id_it_origPKIMessage         1 3 6 1 5 5 7 4 15 */
+&(nid_objs[784]),/* OBJ_id_it_suppLangTags           1 3 6 1 5 5 7 4 16 */
 &(nid_objs[313]),/* OBJ_id_regCtrl                   1 3 6 1 5 5 7 5 1 */
 &(nid_objs[314]),/* OBJ_id_regInfo                   1 3 6 1 5 5 7 5 2 */
 &(nid_objs[323]),/* OBJ_id_alg_des40                 1 3 6 1 5 5 7 6 1 */
@@ -4036,6 +4064,9 @@ static ASN1_OBJECT *obj_objs[NUM_OBJ]={
 &(nid_objs[179]),/* OBJ_ad_ca_issuers                1 3 6 1 5 5 7 48 2 */
 &(nid_objs[363]),/* OBJ_ad_timeStamping              1 3 6 1 5 5 7 48 3 */
 &(nid_objs[364]),/* OBJ_ad_dvcs                      1 3 6 1 5 5 7 48 4 */
+&(nid_objs[785]),/* OBJ_caRepository                 1 3 6 1 5 5 7 48 5 */
+&(nid_objs[780]),/* OBJ_hmac_md5                     1 3 6 1 5 5 8 1 1 */
+&(nid_objs[781]),/* OBJ_hmac_sha1                    1 3 6 1 5 5 8 1 2 */
 &(nid_objs[58]),/* OBJ_netscape_cert_extension      2 16 840 1 113730 1 */
 &(nid_objs[59]),/* OBJ_netscape_data_type           2 16 840 1 113730 2 */
 &(nid_objs[438]),/* OBJ_pilotAttributeType           0 9 2342 19200300 100 1 */
@@ -4044,6 +4075,8 @@ static ASN1_OBJECT *obj_objs[NUM_OBJ]={
 &(nid_objs[441]),/* OBJ_pilotGroups                  0 9 2342 19200300 100 10 */
 &(nid_objs[108]),/* OBJ_cast5_cbc                    1 2 840 113533 7 66 10 */
 &(nid_objs[112]),/* OBJ_pbeWithMD5AndCast5_CBC       1 2 840 113533 7 66 12 */
+&(nid_objs[782]),/* OBJ_id_PasswordBasedMAC          1 2 840 113533 7 66 13 */
+&(nid_objs[783]),/* OBJ_id_DHBasedMac                1 2 840 113533 7 66 30 */
 &(nid_objs[ 6]),/* OBJ_rsaEncryption                1 2 840 113549 1 1 1 */
 &(nid_objs[ 7]),/* OBJ_md2WithRSAEncryption         1 2 840 113549 1 1 2 */
 &(nid_objs[396]),/* OBJ_md4WithRSAEncryption         1 2 840 113549 1 1 3 */
index 68b6e31a9740e8f7c1a70f8e3c5a714209d6279e..e4ce03b3f08d7c93572ebf15fd9f3ed5955aa2c4 100644 (file)
 #define NID_identified_organization            676
 #define OBJ_identified_organization            OBJ_iso,3L
 
+#define SN_hmac_md5            "HMAC-MD5"
+#define LN_hmac_md5            "hmac-md5"
+#define NID_hmac_md5           780
+#define OBJ_hmac_md5           OBJ_identified_organization,6L,1L,5L,5L,8L,1L,1L
+
+#define SN_hmac_sha1           "HMAC-SHA1"
+#define LN_hmac_sha1           "hmac-sha1"
+#define NID_hmac_sha1          781
+#define OBJ_hmac_sha1          OBJ_identified_organization,6L,1L,5L,5L,8L,1L,2L
+
 #define SN_certicom_arc                "certicom-arc"
 #define NID_certicom_arc               677
 #define OBJ_certicom_arc               OBJ_identified_organization,132L
 #define NID_pbeWithMD5AndCast5_CBC             112
 #define OBJ_pbeWithMD5AndCast5_CBC             OBJ_ISO_US,113533L,7L,66L,12L
 
+#define SN_id_PasswordBasedMAC         "id-PasswordBasedMAC"
+#define LN_id_PasswordBasedMAC         "password based MAC"
+#define NID_id_PasswordBasedMAC                782
+#define OBJ_id_PasswordBasedMAC                OBJ_ISO_US,113533L,7L,66L,13L
+
+#define SN_id_DHBasedMac               "id-DHBasedMac"
+#define LN_id_DHBasedMac               "Diffie-Hellman based MAC"
+#define NID_id_DHBasedMac              783
+#define OBJ_id_DHBasedMac              OBJ_ISO_US,113533L,7L,66L,30L
+
 #define SN_rsadsi              "rsadsi"
 #define LN_rsadsi              "RSA Data Security, Inc."
 #define NID_rsadsi             1
 #define NID_id_it_origPKIMessage               312
 #define OBJ_id_it_origPKIMessage               OBJ_id_it,15L
 
+#define SN_id_it_suppLangTags          "id-it-suppLangTags"
+#define NID_id_it_suppLangTags         784
+#define OBJ_id_it_suppLangTags         OBJ_id_it,16L
+
 #define SN_id_regCtrl          "id-regCtrl"
 #define NID_id_regCtrl         313
 #define OBJ_id_regCtrl         OBJ_id_pkip,1L
 #define NID_ad_dvcs            364
 #define OBJ_ad_dvcs            OBJ_id_ad,4L
 
+#define SN_caRepository                "caRepository"
+#define LN_caRepository                "CA Repository"
+#define NID_caRepository               785
+#define OBJ_caRepository               OBJ_id_ad,5L
+
 #define OBJ_id_pkix_OCSP               OBJ_ad_OCSP
 
 #define SN_id_pkix_OCSP_basic          "basicOCSPResponse"
index 76fa050c117b43d00fce587d761ce92b4428fc05..06e4193651b02049e1032413626d5ff6cfbdf6e8 100644 (file)
@@ -777,3 +777,9 @@ seed_ecb            776
 seed_cbc               777
 seed_ofb128            778
 seed_cfb128            779
+hmac_md5               780
+hmac_sha1              781
+id_PasswordBasedMAC            782
+id_DHBasedMac          783
+id_it_suppLangTags             784
+caRepository           785
index 499ff62fbeb871de3df1890c37b56061d3b44a64..bbba5ed04b9164d8e99d1c71f8a0d6278f470259 100644 (file)
@@ -11,6 +11,10 @@ iso 2                        : member-body           : ISO Member Body
 
 iso 3                  : identified-organization
 
+# HMAC OIDs
+identified-organization 6 1 5 5 8 1 1  : HMAC-MD5      : hmac-md5
+identified-organization 6 1 5 5 8 1 2  : HMAC-SHA1     : hmac-sha1
+
 identified-organization 132    : certicom-arc
 
 joint-iso-itu-t 23     : international-organizations   : International Organizations
@@ -141,6 +145,10 @@ ISO-US 113533 7 66 10      : CAST5-CBC             : cast5-cbc
 !Cname pbeWithMD5AndCast5-CBC
 ISO-US 113533 7 66 12  :                       : pbeWithMD5AndCast5CBC
 
+# Macs for CMP and CRMF
+ISO-US 113533 7 66 13  : id-PasswordBasedMAC   : password based MAC
+ISO-US 113533 7 66 30  : id-DHBasedMac         : Diffie-Hellman based MAC
+
 ISO-US 113549          : rsadsi                : RSA Data Security, Inc.
 
 rsadsi 1               : pkcs                  : RSA Data Security, Inc. PKCS
@@ -484,6 +492,7 @@ id-it 12            : id-it-revPassphrase
 id-it 13               : id-it-implicitConfirm
 id-it 14               : id-it-confirmWaitTime
 id-it 15               : id-it-origPKIMessage
+id-it 16               : id-it-suppLangTags
 
 # CRMF registration
 id-pkip 1              : id-regCtrl
@@ -570,6 +579,7 @@ id-ad 2                     : caIssuers             : CA Issuers
 id-ad 3                        : ad_timestamping       : AD Time Stamping
 !Cname ad-dvcs
 id-ad 4                        : AD_DVCS               : ad dvcs
+id-ad 5                        : caRepository          : CA Repository
 
 
 !Alias id-pkix-OCSP ad-OCSP
index 53f3364af0c403e0aebda6697ad8321f74466b24..a0577a717ef49ca00e8743bfb2d6f118ed3da95a 100644 (file)
@@ -186,11 +186,11 @@ typedef struct ocsp_resp_bytes_st
  *      responseStatus         OCSPResponseStatus,
  *      responseBytes          [0] EXPLICIT ResponseBytes OPTIONAL }
  */
-typedef struct ocsp_response_st
+struct ocsp_response_st
        {
        ASN1_ENUMERATED *responseStatus;
        OCSP_RESPBYTES  *responseBytes;
-       } OCSP_RESPONSE;
+       };
 
 /*   ResponderID ::= CHOICE {
  *      byName   [1] Name,
@@ -198,14 +198,18 @@ typedef struct ocsp_response_st
  */
 #define V_OCSP_RESPID_NAME 0
 #define V_OCSP_RESPID_KEY  1
-typedef struct ocsp_responder_id_st
+struct ocsp_responder_id_st
        {
        int type;
        union   {
                X509_NAME* byName;
                ASN1_OCTET_STRING *byKey;
                } value;
-       } OCSP_RESPID;
+       };
+
+DECLARE_STACK_OF(OCSP_RESPID)
+DECLARE_ASN1_FUNCTIONS(OCSP_RESPID)
+
 /*   KeyHash ::= OCTET STRING --SHA-1 hash of responder's public key
  *                            --(excluding the tag and length fields)
  */
@@ -397,6 +401,10 @@ typedef struct ocsp_service_locator_st
                (char *(*)())d2i_OCSP_CERTSTATUS,(char *)(cs))
 
 OCSP_RESPONSE *OCSP_sendreq_bio(BIO *b, char *path, OCSP_REQUEST *req);
+OCSP_REQ_CTX *OCSP_sendreq_new(BIO *io, char *path, OCSP_REQUEST *req,
+                                                               int maxline);
+int OCSP_sendreq_nbio(OCSP_RESPONSE **presp, OCSP_REQ_CTX *rctx);
+void OCSP_REQ_CTX_free(OCSP_REQ_CTX *rctx);
 
 OCSP_CERTID *OCSP_cert_to_id(const EVP_MD *dgst, X509 *subject, X509 *issuer);
 
@@ -469,7 +477,7 @@ int OCSP_basic_sign(OCSP_BASICRESP *brsp,
 ASN1_STRING *ASN1_STRING_encode(ASN1_STRING *s, i2d_of_void *i2d,
                                void *data, STACK_OF(ASN1_OBJECT) *sk);
 #define ASN1_STRING_encode_of(type,s,i2d,data,sk) \
-((ASN1_STRING *(*)(ASN1_STRING *,I2D_OF(type),type *,STACK_OF(ASN1_OBJECT) *))openssl_fcast(ASN1_STRING_encode))(s,i2d,data,sk)
+       ASN1_STRING_encode(s, CHECKED_I2D_OF(type, i2d), data, sk)
 
 X509_EXTENSION *OCSP_crlID_new(char *url, long *n, char *tim);
 
@@ -574,6 +582,7 @@ void ERR_load_OCSP_strings(void);
 #define OCSP_F_OCSP_REQUEST_VERIFY                      116
 #define OCSP_F_OCSP_RESPONSE_GET1_BASIC                         111
 #define OCSP_F_OCSP_SENDREQ_BIO                                 112
+#define OCSP_F_PARSE_HTTP_LINE1                                 117
 #define OCSP_F_REQUEST_VERIFY                           113
 
 /* Reason codes. */
index ad62364f298e4b3fc8d5e3f6967bb7a8b6ae8f6c..d2f2e79f444c394e057ffb213d43329e160df17c 100644 (file)
@@ -1,6 +1,6 @@
 /* crypto/ocsp/ocsp_err.c */
 /* ====================================================================
- * Copyright (c) 1999-2005 The OpenSSL Project.  All rights reserved.
+ * Copyright (c) 1999-2007 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
@@ -86,6 +86,7 @@ static ERR_STRING_DATA OCSP_str_functs[]=
 {ERR_FUNC(OCSP_F_OCSP_REQUEST_VERIFY), "OCSP_request_verify"},
 {ERR_FUNC(OCSP_F_OCSP_RESPONSE_GET1_BASIC),    "OCSP_response_get1_basic"},
 {ERR_FUNC(OCSP_F_OCSP_SENDREQ_BIO),    "OCSP_sendreq_bio"},
+{ERR_FUNC(OCSP_F_PARSE_HTTP_LINE1),    "PARSE_HTTP_LINE1"},
 {ERR_FUNC(OCSP_F_REQUEST_VERIFY),      "REQUEST_VERIFY"},
 {0,NULL}
        };
index 9213e58ae49c126f01c587c46d0c105b041c0e54..a8e569b74a0c18fdc1791f975001b21d70800f9b 100644 (file)
@@ -1,9 +1,9 @@
 /* ocsp_ht.c */
 /* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
- * project 2000.
+ * project 2006.
  */
 /* ====================================================================
- * Copyright (c) 2000 The OpenSSL Project.  All rights reserved.
+ * Copyright (c) 2006 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
 #define strtoul (unsigned long)strtol
 #endif /* OPENSSL_SYS_SUNOS */
 
-/* Quick and dirty HTTP OCSP request handler.
- * Could make this a bit cleverer by adding
- * support for non blocking BIOs and a few
- * other refinements.
- */
+/* Stateful OCSP request code, supporting non-blocking I/O */
 
-OCSP_RESPONSE *OCSP_sendreq_bio(BIO *b, char *path, OCSP_REQUEST *req)
-{
-       BIO *mem = NULL;
-       char tmpbuf[1024];
-       OCSP_RESPONSE *resp = NULL;
-       char *p, *q, *r;
-       int len, retcode;
-       static char req_txt[] =
-"POST %s HTTP/1.0\r\n\
-Content-Type: application/ocsp-request\r\n\
-Content-Length: %d\r\n\r\n";
-
-       len = i2d_OCSP_REQUEST(req, NULL);
-       if(BIO_printf(b, req_txt, path, len) < 0) {
-               OCSPerr(OCSP_F_OCSP_SENDREQ_BIO,OCSP_R_SERVER_WRITE_ERROR);
-               goto err;
-       }
-       if(i2d_OCSP_REQUEST_bio(b, req) <= 0) {
-               OCSPerr(OCSP_F_OCSP_SENDREQ_BIO,OCSP_R_SERVER_WRITE_ERROR);
-               goto err;
+/* Opaque OCSP request status structure */
+
+struct ocsp_req_ctx_st {
+       int state;              /* Current I/O state */
+       unsigned char *iobuf;   /* Line buffer */
+       int iobuflen;           /* Line buffer length */
+       BIO *io;                /* BIO to perform I/O with */
+       BIO *mem;               /* Memory BIO response is built into */
+       unsigned long asn1_len; /* ASN1 length of response */
+       };
+
+#define OCSP_MAX_REQUEST_LENGTH        (100 * 1024)
+#define OCSP_MAX_LINE_LEN      4096;
+
+/* OCSP states */
+
+/* If set no reading should be performed */
+#define OHS_NOREAD             0x1000
+/* Error condition */
+#define OHS_ERROR              (0 | OHS_NOREAD)
+/* First line being read */
+#define OHS_FIRSTLINE          1
+/* MIME headers being read */
+#define OHS_HEADERS            2
+/* OCSP initial header (tag + length) being read */
+#define OHS_ASN1_HEADER                3
+/* OCSP content octets being read */
+#define OHS_ASN1_CONTENT       4
+/* Request being sent */
+#define OHS_ASN1_WRITE         (6 | OHS_NOREAD)
+/* Request being flushed */
+#define OHS_ASN1_FLUSH         (7 | OHS_NOREAD)
+/* Completed */
+#define OHS_DONE               (8 | OHS_NOREAD)
+
+
+static int parse_http_line1(char *line);
+
+void OCSP_REQ_CTX_free(OCSP_REQ_CTX *rctx)
+       {
+       if (rctx->mem)
+               BIO_free(rctx->mem);
+       if (rctx->iobuf)
+               OPENSSL_free(rctx->iobuf);
+       OPENSSL_free(rctx);
        }
-       if(!(mem = BIO_new(BIO_s_mem()))) goto err;
-       /* Copy response to a memory BIO: socket bios can't do gets! */
-       while ((len = BIO_read(b, tmpbuf, sizeof tmpbuf))) {
-               if(len < 0) {
-                       OCSPerr(OCSP_F_OCSP_SENDREQ_BIO,OCSP_R_SERVER_READ_ERROR);
-                       goto err;
+
+OCSP_REQ_CTX *OCSP_sendreq_new(BIO *io, char *path, OCSP_REQUEST *req,
+                                                               int maxline)
+       {
+       static char post_hdr[] = "POST %s HTTP/1.0\r\n"
+       "Content-Type: application/ocsp-request\r\n"
+       "Content-Length: %d\r\n\r\n";
+
+       OCSP_REQ_CTX *rctx;
+       rctx = OPENSSL_malloc(sizeof(OCSP_REQ_CTX));
+       rctx->state = OHS_FIRSTLINE;
+       rctx->mem = BIO_new(BIO_s_mem());
+       rctx->io = io;
+       if (maxline > 0)
+               rctx->iobuflen = maxline;
+       else
+               rctx->iobuflen = OCSP_MAX_LINE_LEN;
+       rctx->iobuf = OPENSSL_malloc(rctx->iobuflen);
+       if (!path)
+               path = "/";
+
+        if (BIO_printf(rctx->mem, post_hdr, path,
+                               i2d_OCSP_REQUEST(req, NULL)) <= 0)
+               {
+               rctx->state = OHS_ERROR;
+               return 0;
                }
-               BIO_write(mem, tmpbuf, len);
-       }
-       if(BIO_gets(mem, tmpbuf, 512) <= 0) {
-               OCSPerr(OCSP_F_OCSP_SENDREQ_BIO,OCSP_R_SERVER_RESPONSE_PARSE_ERROR);
-               goto err;
+        if (i2d_OCSP_REQUEST_bio(rctx->mem, req) <= 0)
+               {
+               rctx->state = OHS_ERROR;
+               return 0;
+               }
+       rctx->state = OHS_ASN1_WRITE;
+       rctx->asn1_len = BIO_get_mem_data(rctx->mem, NULL);
+
+       return rctx;
        }
-       /* Parse the HTTP response. This will look like this:
-        * "HTTP/1.0 200 OK". We need to obtain the numeric code and
-         * (optional) informational message.
-        */
 
+/* Parse the HTTP response. This will look like this:
+ * "HTTP/1.0 200 OK". We need to obtain the numeric code and
+ * (optional) informational message.
+ */
+
+static int parse_http_line1(char *line)
+       {
+       int retcode;
+       char *p, *q, *r;
        /* Skip to first white space (passed protocol info) */
-       for(p = tmpbuf; *p && !isspace((unsigned char)*p); p++) continue;
-       if(!*p) {
-               OCSPerr(OCSP_F_OCSP_SENDREQ_BIO,OCSP_R_SERVER_RESPONSE_PARSE_ERROR);
-               goto err;
-       }
+
+       for(p = line; *p && !isspace((unsigned char)*p); p++)
+               continue;
+       if(!*p)
+               {
+               OCSPerr(OCSP_F_PARSE_HTTP_LINE1,
+                                       OCSP_R_SERVER_RESPONSE_PARSE_ERROR);
+               return 0;
+               }
+
        /* Skip past white space to start of response code */
-       while(*p && isspace((unsigned char)*p)) p++;
-       if(!*p) {
-               OCSPerr(OCSP_F_OCSP_SENDREQ_BIO,OCSP_R_SERVER_RESPONSE_PARSE_ERROR);
-               goto err;
-       }
+       while(*p && isspace((unsigned char)*p))
+               p++;
+
+       if(!*p)
+               {
+               OCSPerr(OCSP_F_PARSE_HTTP_LINE1,
+                                       OCSP_R_SERVER_RESPONSE_PARSE_ERROR);
+               return 0;
+               }
+
        /* Find end of response code: first whitespace after start of code */
-       for(q = p; *q && !isspace((unsigned char)*q); q++) continue;
-       if(!*q) {
-               OCSPerr(OCSP_F_OCSP_SENDREQ_BIO,OCSP_R_SERVER_RESPONSE_PARSE_ERROR);
-               goto err;
-       }
+       for(q = p; *q && !isspace((unsigned char)*q); q++)
+               continue;
+
+       if(!*q)
+               {
+               OCSPerr(OCSP_F_PARSE_HTTP_LINE1,
+                                       OCSP_R_SERVER_RESPONSE_PARSE_ERROR);
+               return 0;
+               }
+
        /* Set end of response code and start of message */ 
        *q++ = 0;
+
        /* Attempt to parse numeric code */
        retcode = strtoul(p, &r, 10);
-       if(*r) goto err;
+
+       if(*r)
+               return 0;
+
        /* Skip over any leading white space in message */
-       while(*q && isspace((unsigned char)*q))  q++;
-       if(*q) {
-       /* Finally zap any trailing white space in message (include CRLF) */
-       /* We know q has a non white space character so this is OK */
-               for(r = q + strlen(q) - 1; isspace((unsigned char)*r); r--) *r = 0;
-       }
-       if(retcode != 200) {
-               OCSPerr(OCSP_F_OCSP_SENDREQ_BIO,OCSP_R_SERVER_RESPONSE_ERROR);
-               if(!*q) { 
-                       ERR_add_error_data(2, "Code=", p);
+       while(*q && isspace((unsigned char)*q))
+               q++;
+
+       if(*q)
+               {
+               /* Finally zap any trailing white space in message (include
+                * CRLF) */
+
+               /* We know q has a non white space character so this is OK */
+               for(r = q + strlen(q) - 1; isspace((unsigned char)*r); r--)
+                       *r = 0;
                }
-               else {
+       if(retcode != 200)
+               {
+               OCSPerr(OCSP_F_PARSE_HTTP_LINE1, OCSP_R_SERVER_RESPONSE_ERROR);
+               if(!*q)
+                       ERR_add_error_data(2, "Code=", p);
+               else
                        ERR_add_error_data(4, "Code=", p, ",Reason=", q);
+               return 0;
                }
-               goto err;
+
+
+       return 1;
+
        }
-       /* Find blank line marking beginning of content */      
-       while(BIO_gets(mem, tmpbuf, 512) > 0)
+
+int OCSP_sendreq_nbio(OCSP_RESPONSE **presp, OCSP_REQ_CTX *rctx)
        {
-               for(p = tmpbuf; *p && isspace((unsigned char)*p); p++) continue;
-               if(!*p) break;
-       }
-       if(*p) {
-               OCSPerr(OCSP_F_OCSP_SENDREQ_BIO,OCSP_R_NO_CONTENT);
-               goto err;
+       int i, n;
+       const unsigned char *p;
+       next_io:
+       if (!(rctx->state & OHS_NOREAD))
+               {
+               n = BIO_read(rctx->io, rctx->iobuf, rctx->iobuflen);
+
+               if (n <= 0)
+                       {
+                       if (BIO_should_retry(rctx->io))
+                               return -1;
+                       return 0;
+                       }
+
+               /* Write data to memory BIO */
+
+               if (BIO_write(rctx->mem, rctx->iobuf, n) != n)
+                       return 0;
+               }
+
+       switch(rctx->state)
+               {
+
+               case OHS_ASN1_WRITE:
+               n = BIO_get_mem_data(rctx->mem, &p);
+
+               i = BIO_write(rctx->io,
+                       p + (n - rctx->asn1_len), rctx->asn1_len);
+
+               if (i <= 0)
+                       {
+                       if (BIO_should_retry(rctx->io))
+                               return -1;
+                       rctx->state = OHS_ERROR;
+                       return 0;
+                       }
+
+               rctx->asn1_len -= i;
+
+               if (rctx->asn1_len > 0)
+                       goto next_io;
+
+               rctx->state = OHS_ASN1_FLUSH;
+
+               (void)BIO_reset(rctx->mem);
+
+               case OHS_ASN1_FLUSH:
+
+               i = BIO_flush(rctx->io);
+
+               if (i > 0)
+                       {
+                       rctx->state = OHS_FIRSTLINE;
+                       goto next_io;
+                       }
+
+               if (BIO_should_retry(rctx->io))
+                       return -1;
+
+               rctx->state = OHS_ERROR;
+               return 0;
+
+               case OHS_ERROR:
+               return 0;
+
+               case OHS_FIRSTLINE:
+               case OHS_HEADERS:
+
+               /* Attempt to read a line in */
+
+               next_line:
+               /* Due to &%^*$" memory BIO behaviour with BIO_gets we
+                * have to check there's a complete line in there before
+                * calling BIO_gets or we'll just get a partial read.
+                */
+               n = BIO_get_mem_data(rctx->mem, &p);
+               if ((n <= 0) || !memchr(p, '\n', n))
+                       {
+                       if (n >= rctx->iobuflen)
+                               {
+                               rctx->state = OHS_ERROR;
+                               return 0;
+                               }
+                       goto next_io;
+                       }
+               n = BIO_gets(rctx->mem, (char *)rctx->iobuf, rctx->iobuflen);
+
+               if (n <= 0)
+                       {
+                       if (BIO_should_retry(rctx->mem))
+                               goto next_io;
+                       rctx->state = OHS_ERROR;
+                       return 0;
+                       }
+
+               /* Don't allow excessive lines */
+               if (n == rctx->iobuflen)
+                       {
+                       rctx->state = OHS_ERROR;
+                       return 0;
+                       }
+
+               /* First line */
+               if (rctx->state == OHS_FIRSTLINE)
+                       {
+                       if (parse_http_line1((char *)rctx->iobuf))
+                               {
+                               rctx->state = OHS_HEADERS;
+                               goto next_line;
+                               }
+                       else
+                               {
+                               rctx->state = OHS_ERROR;
+                               return 0;
+                               }
+                       }
+               else
+                       {
+                       /* Look for blank line: end of headers */
+                       for (p = rctx->iobuf; *p; p++)
+                               {
+                               if ((*p != '\r') && (*p != '\n'))
+                                       break;
+                               }
+                       if (*p)
+                               goto next_line;
+
+                       rctx->state = OHS_ASN1_HEADER;
+
+                       }
+               /* Fall thru */
+
+
+               case OHS_ASN1_HEADER:
+               /* Now reading ASN1 header: can read at least 6 bytes which
+                * is more than enough for any valid ASN1 SEQUENCE header
+                */
+               n = BIO_get_mem_data(rctx->mem, &p);
+               if (n < 6)
+                       goto next_io;
+
+               /* Check it is an ASN1 SEQUENCE */
+               if (*p++ != (V_ASN1_SEQUENCE|V_ASN1_CONSTRUCTED))
+                       {
+                       rctx->state = OHS_ERROR;
+                       return 0;
+                       }
+
+               /* Check out length field */
+               if (*p & 0x80)
+                       {
+                       n = *p & 0x7F;
+                       /* Not NDEF or excessive length */
+                       if (!n || (n > 4))
+                               {
+                               rctx->state = OHS_ERROR;
+                               return 0;
+                               }
+                       p++;
+                       rctx->asn1_len = 0;
+                       for (i = 0; i < n; i++)
+                               {
+                               rctx->asn1_len <<= 8;
+                               rctx->asn1_len |= *p++;
+                               }
+
+                       if (rctx->asn1_len > OCSP_MAX_REQUEST_LENGTH)
+                               {
+                               rctx->state = OHS_ERROR;
+                               return 0;
+                               }
+
+                       rctx->asn1_len += n + 2;
+                       }
+               else
+                       rctx->asn1_len = *p + 2;
+
+               rctx->state = OHS_ASN1_CONTENT;
+
+               /* Fall thru */
+               
+               case OHS_ASN1_CONTENT:
+               n = BIO_get_mem_data(rctx->mem, &p);
+               if (n < (int)rctx->asn1_len)
+                       goto next_io;
+
+
+               *presp = d2i_OCSP_RESPONSE(NULL, &p, rctx->asn1_len);
+               if (*presp)
+                       {
+                       rctx->state = OHS_DONE;
+                       return 1;
+                       }
+
+               rctx->state = OHS_ERROR;
+               return 0;
+
+               break;
+
+               case OHS_DONE:
+               return 1;
+
+               }
+
+
+
+       return 0;
+
+
        }
-       if(!(resp = d2i_OCSP_RESPONSE_bio(mem, NULL))) {
-               OCSPerr(OCSP_F_OCSP_SENDREQ_BIO,ERR_R_NESTED_ASN1_ERROR);
-               goto err;
+
+/* Blocking OCSP request handler: now a special case of non-blocking I/O */
+
+OCSP_RESPONSE *OCSP_sendreq_bio(BIO *b, char *path, OCSP_REQUEST *req)
+       {
+       OCSP_RESPONSE *resp = NULL;
+       OCSP_REQ_CTX *ctx;
+       int rv;
+
+       ctx = OCSP_sendreq_new(b, path, req, -1);
+
+       do
+               {
+               rv = OCSP_sendreq_nbio(&resp, ctx);
+               } while ((rv == -1) && BIO_should_retry(b));
+
+       OCSP_REQ_CTX_free(ctx);
+
+       if (rv)
+               return resp;
+
+       return NULL;
        }
-       err:
-       BIO_free(mem);
-       return resp;
-}
index 8dc1ef545a44d80f89a1a54ce8c4dee70c3cf3d9..e09ca54ec18ebe74166fa7d75b15f885409c649a 100644 (file)
  * (Prior to 0.9.5a beta1, a different scheme was used: MMNNFFRBB for
  *  major minor fix final patch/beta)
  */
-#define OPENSSL_VERSION_NUMBER 0x00908060L
+#define OPENSSL_VERSION_NUMBER 0x00908080L
 #ifdef OPENSSL_FIPS
-#define OPENSSL_VERSION_TEXT   "OpenSSL 0.9.8f-fips-dev xx XXXX xxxx"
+#define OPENSSL_VERSION_TEXT   "OpenSSL 0.9.8h-fips-dev xx XXX xxxx"
 #else
-#define OPENSSL_VERSION_TEXT   "OpenSSL 0.9.8f-dev xx XXXX xxxx"
+#define OPENSSL_VERSION_TEXT   "OpenSSL 0.9.8h-dev xx XXX xxxx"
 #endif
 #define OPENSSL_VERSION_PTEXT  " part of " OPENSSL_VERSION_TEXT
 
index 9c335a181909da585d16205bd7c0105318f0e123..08c2968f122d27373659258120ccc3edd6c0963d 100644 (file)
@@ -171,4 +171,8 @@ typedef void CRYPTO_EX_free(void *parent, void *ptr, CRYPTO_EX_DATA *ad,
 typedef int CRYPTO_EX_dup(CRYPTO_EX_DATA *to, CRYPTO_EX_DATA *from, void *from_d, 
                                        int idx, long argl, void *argp);
 
+typedef struct ocsp_req_ctx_st OCSP_REQ_CTX;
+typedef struct ocsp_response_st OCSP_RESPONSE;
+typedef struct ocsp_responder_id_st OCSP_RESPID;
+
 #endif /* def HEADER_OPENSSL_TYPES_H */
index c28706ddc033118872cb1b6344c24333b51c90b1..4e24cc5b5228119cdb95e8df6ce3d01fc1525fa4 100644 (file)
@@ -220,19 +220,28 @@ typedef struct pem_ctx_st
 #define IMPLEMENT_PEM_read_fp(name, type, str, asn1) \
 type *PEM_read_##name(FILE *fp, type **x, pem_password_cb *cb, void *u)\
 { \
-return(((type *(*)(D2I_OF(type),char *,FILE *,type **,pem_password_cb *,void *))openssl_fcast(PEM_ASN1_read))(d2i_##asn1, str,fp,x,cb,u)); \
+    return (type*)PEM_ASN1_read(CHECKED_D2I_OF(type, d2i_##asn1), \
+                               str, fp, \
+                               CHECKED_PPTR_OF(type, x), \
+                               cb, u); \
 } 
 
 #define IMPLEMENT_PEM_write_fp(name, type, str, asn1) \
 int PEM_write_##name(FILE *fp, type *x) \
 { \
-return(((int (*)(I2D_OF(type),const char *,FILE *,type *, const EVP_CIPHER *,unsigned char *,int, pem_password_cb *,void *))openssl_fcast(PEM_ASN1_write))(i2d_##asn1,str,fp,x,NULL,NULL,0,NULL,NULL)); \
+    return PEM_ASN1_write(CHECKED_I2D_OF(type, i2d_##asn1), \
+                         str, fp, \
+                         CHECKED_PTR_OF(type, x), \
+                         NULL, NULL, 0, NULL, NULL); \
 }
 
 #define IMPLEMENT_PEM_write_fp_const(name, type, str, asn1) \
 int PEM_write_##name(FILE *fp, const type *x) \
 { \
-return(((int (*)(I2D_OF_const(type),const char *,FILE *, const type *, const EVP_CIPHER *,unsigned char *,int, pem_password_cb *,void *))openssl_fcast(PEM_ASN1_write))(i2d_##asn1,str,fp,x,NULL,NULL,0,NULL,NULL)); \
+    return PEM_ASN1_write(CHECKED_I2D_OF(const type, i2d_##asn1), \
+                         str, fp, \
+                         CHECKED_PTR_OF(const type, x), \
+                         NULL, NULL, 0, NULL, NULL); \
 }
 
 #define IMPLEMENT_PEM_write_cb_fp(name, type, str, asn1) \
@@ -240,7 +249,10 @@ int PEM_write_##name(FILE *fp, type *x, const EVP_CIPHER *enc, \
             unsigned char *kstr, int klen, pem_password_cb *cb, \
                  void *u) \
        { \
-       return(((int (*)(I2D_OF(type),const char *,FILE *,type *, const EVP_CIPHER *,unsigned char *,int, pem_password_cb *,void *))openssl_fcast(PEM_ASN1_write))(i2d_##asn1,str,fp,x,enc,kstr,klen,cb,u)); \
+           return PEM_ASN1_write(CHECKED_I2D_OF(type, i2d_##asn1), \
+                                 str, fp, \
+                                 CHECKED_PTR_OF(type, x), \
+                                 enc, kstr, klen, cb, u); \
        }
 
 #define IMPLEMENT_PEM_write_cb_fp_const(name, type, str, asn1) \
@@ -248,7 +260,10 @@ int PEM_write_##name(FILE *fp, type *x, const EVP_CIPHER *enc, \
             unsigned char *kstr, int klen, pem_password_cb *cb, \
                  void *u) \
        { \
-       return(((int (*)(I2D_OF_const(type),const char *,FILE *,type *, const EVP_CIPHER *,unsigned char *,int, pem_password_cb *,void *))openssl_fcast(PEM_ASN1_write))(i2d_##asn1,str,fp,x,enc,kstr,klen,cb,u)); \
+           return PEM_ASN1_write(CHECKED_I2D_OF(const type, i2d_##asn1), \
+                                 str, fp, \
+                                 CHECKED_PTR_OF(const type, x), \
+                                 enc, kstr, klen, cb, u); \
        }
 
 #endif
@@ -256,33 +271,48 @@ int PEM_write_##name(FILE *fp, type *x, const EVP_CIPHER *enc, \
 #define IMPLEMENT_PEM_read_bio(name, type, str, asn1) \
 type *PEM_read_bio_##name(BIO *bp, type **x, pem_password_cb *cb, void *u)\
 { \
-return(((type *(*)(D2I_OF(type),const char *,BIO *,type **,pem_password_cb *,void *))openssl_fcast(PEM_ASN1_read_bio))(d2i_##asn1, str,bp,x,cb,u)); \
+    return (type*)PEM_ASN1_read_bio(CHECKED_D2I_OF(type, d2i_##asn1), \
+                                   str, bp, \
+                                   CHECKED_PPTR_OF(type, x), \
+                                   cb, u); \
 }
 
 #define IMPLEMENT_PEM_write_bio(name, type, str, asn1) \
 int PEM_write_bio_##name(BIO *bp, type *x) \
 { \
-return(((int (*)(I2D_OF(type),const char *,BIO *,type *, const EVP_CIPHER *,unsigned char *,int, pem_password_cb *,void *))openssl_fcast(PEM_ASN1_write_bio))(i2d_##asn1,str,bp,x,NULL,NULL,0,NULL,NULL)); \
+    return PEM_ASN1_write_bio(CHECKED_I2D_OF(type, i2d_##asn1), \
+                             str, bp, \
+                             CHECKED_PTR_OF(type, x), \
+                             NULL, NULL, 0, NULL, NULL); \
 }
 
 #define IMPLEMENT_PEM_write_bio_const(name, type, str, asn1) \
 int PEM_write_bio_##name(BIO *bp, const type *x) \
 { \
-return(((int (*)(I2D_OF_const(type),const char *,BIO *,const type *, const EVP_CIPHER *,unsigned char *,int, pem_password_cb *,void *))openssl_fcast(PEM_ASN1_write_bio))(i2d_##asn1,str,bp,x,NULL,NULL,0,NULL,NULL)); \
+    return PEM_ASN1_write_bio(CHECKED_I2D_OF(const type, i2d_##asn1), \
+                             str, bp, \
+                             CHECKED_PTR_OF(const type, x), \
+                             NULL, NULL, 0, NULL, NULL); \
 }
 
 #define IMPLEMENT_PEM_write_cb_bio(name, type, str, asn1) \
 int PEM_write_bio_##name(BIO *bp, type *x, const EVP_CIPHER *enc, \
             unsigned char *kstr, int klen, pem_password_cb *cb, void *u) \
        { \
-       return(((int (*)(I2D_OF(type),const char *,BIO *,type *,const EVP_CIPHER *,unsigned char *,int,pem_password_cb *,void *))openssl_fcast(PEM_ASN1_write_bio))(i2d_##asn1,str,bp,x,enc,kstr,klen,cb,u)); \
+           return PEM_ASN1_write_bio(CHECKED_I2D_OF(type, i2d_##asn1), \
+                                     str, bp, \
+                                     CHECKED_PTR_OF(type, x), \
+                                     enc, kstr, klen, cb, u); \
        }
 
 #define IMPLEMENT_PEM_write_cb_bio_const(name, type, str, asn1) \
 int PEM_write_bio_##name(BIO *bp, type *x, const EVP_CIPHER *enc, \
             unsigned char *kstr, int klen, pem_password_cb *cb, void *u) \
        { \
-       return(((int (*)(I2D_OF_const(type),const char *,BIO *,type *,const EVP_CIPHER *,unsigned char *,int,pem_password_cb *,void *))openssl_fcast(PEM_ASN1_write_bio))(i2d_##asn1,str,bp,x,enc,kstr,klen,cb,u)); \
+           return PEM_ASN1_write_bio(CHECKED_I2D_OF(const type, i2d_##asn1), \
+                                     str, bp, \
+                                     CHECKED_PTR_OF(const type, x), \
+                                     enc, kstr, klen, cb, u); \
        }
 
 #define IMPLEMENT_PEM_write(name, type, str, asn1) \
@@ -545,13 +575,22 @@ int PEM_bytes_read_bio(unsigned char **pdata, long *plen, char **pnm, const char
             pem_password_cb *cb, void *u);
 void * PEM_ASN1_read_bio(d2i_of_void *d2i, const char *name, BIO *bp,
                          void **x, pem_password_cb *cb, void *u);
+
 #define PEM_ASN1_read_bio_of(type,d2i,name,bp,x,cb,u) \
-((type *(*)(D2I_OF(type),const char *,BIO *,type **,pem_password_cb *,void *))openssl_fcast(PEM_ASN1_read_bio))(d2i,name,bp,x,cb,u)
+    ((type*)PEM_ASN1_read_bio(CHECKED_D2I_OF(type, d2i), \
+                             name, bp,                 \
+                             CHECKED_PPTR_OF(type, x), \
+                             cb, u))
+
 int    PEM_ASN1_write_bio(i2d_of_void *i2d,const char *name,BIO *bp,char *x,
                           const EVP_CIPHER *enc,unsigned char *kstr,int klen,
                           pem_password_cb *cb, void *u);
+
 #define PEM_ASN1_write_bio_of(type,i2d,name,bp,x,enc,kstr,klen,cb,u) \
-       ((int (*)(I2D_OF(type),const char *,BIO *,type *, const EVP_CIPHER *,unsigned char *,int, pem_password_cb *,void *))openssl_fcast(PEM_ASN1_write_bio))(i2d,name,bp,x,enc,kstr,klen,cb,u)
+    (PEM_ASN1_write_bio(CHECKED_I2D_OF(type, i2d), \
+                       name, bp,                  \
+                       CHECKED_PTR_OF(type, x), \
+                       enc, kstr, klen, cb, u))
 
 STACK_OF(X509_INFO) *  PEM_X509_INFO_read_bio(BIO *bp, STACK_OF(X509_INFO) *sk, pem_password_cb *cb, void *u);
 int    PEM_X509_INFO_write_bio(BIO *bp,X509_INFO *xi, EVP_CIPHER *enc,
index 105e4e07ad98b74a2f6b9ef76c0f51c364b668f8..28b2ebfd141c5697d1e580479c49b6bb58118fa2 100644 (file)
@@ -220,7 +220,6 @@ void RAND_add(const void *buf, int num, double entropy)
 int RAND_bytes(unsigned char *buf, int num)
        {
        const RAND_METHOD *meth = RAND_get_rand_method();
-       memset(buf, 0, num);
        if (meth && meth->bytes)
                return meth->bytes(buf,num);
        return(-1);
@@ -229,7 +228,6 @@ int RAND_bytes(unsigned char *buf, int num)
 int RAND_pseudo_bytes(unsigned char *buf, int num)
        {
        const RAND_METHOD *meth = RAND_get_rand_method();
-       memset(buf, 0, num);
        if (meth && meth->pseudorand)
                return meth->pseudorand(buf,num);
        return(-1);
index cbfdf2ae6ff23390818936227a8d6f74adf9b7f5..fb34e0e836c9c32312cd2c0aedd6f5d1333733c0 100644 (file)
@@ -103,12 +103,12 @@ static char *pt(unsigned char *md);
 int main(int argc, char *argv[])
        {
        int i,err=0;
-       unsigned char **P,**R;
+       char **P,**R;
        char *p;
        unsigned char md[RIPEMD160_DIGEST_LENGTH];
 
-       P=(unsigned char **)test;
-       R=(unsigned char **)ret;
+       P=test;
+       R=ret;
        i=1;
        while (*P != NULL)
                {
index 93a4f017965ae200f1d357585419105c29bd69f2..f7ed67a72609ef6cfb0fd396e8e2f9aa7d12a90a 100755 (executable)
@@ -27,7 +27,7 @@
 #              gcc 3.4         32-bit asm      cycles/byte
 # Opteron      +45%            +20%            6.8
 # Xeon P4      +65%            +0%             9.9
-# Core2                +60%            +10%            8.8
+# Core2                +60%            +10%            7.0
 
 $output=shift;
 
index b0650c7254f2e3e7b1f446b2c393544bab7240c4..6feb3964c7577f6083532d098fff25b45f213962 100644 (file)
@@ -106,7 +106,7 @@ static char *pt(unsigned char *md);
 int main(int argc, char *argv[])
        {
        int i,err=0;
-       unsigned char **P,**R;
+       char **P,**R;
        static unsigned char buf[1000];
        char *p,*r;
        EVP_MD_CTX c;
@@ -118,8 +118,8 @@ int main(int argc, char *argv[])
 #endif
 
        EVP_MD_CTX_init(&c);
-       P=(unsigned char **)test;
-       R=(unsigned char **)ret;
+       P=test;
+       R=ret;
        i=1;
        while (*P != NULL)
                {
index d496f365c2703a590ddd2d195d32d0b1158990d0..c3b7ed53db0840f86283c4514228d8d8fc7f9e4c 100644 (file)
 
 #include <openssl/stack.h>
 
-typedef void (*openssl_fptr)(void);
-#define openssl_fcast(f) ((openssl_fptr)f)
-
 #ifdef DEBUG_SAFESTACK
 
+#ifndef CHECKED_PTR_OF
+#define CHECKED_PTR_OF(type, p) \
+    ((void*) (1 ? p : (type*)0))
+#endif
+
+#define CHECKED_SK_FREE_FUNC(type, p) \
+    ((void (*)(void *)) ((1 ? p : (void (*)(type *))0)))
+
+#define CHECKED_SK_CMP_FUNC(type, p) \
+    ((int (*)(const char * const *, const char * const *)) \
+       ((1 ? p : (int (*)(const type * const *, const type * const *))0)))
+
 #define STACK_OF(type) struct stack_st_##type
 #define PREDECLARE_STACK_OF(type) STACK_OF(type);
 
@@ -76,76 +85,71 @@ STACK_OF(type) \
 /* SKM_sk_... stack macros are internal to safestack.h:
  * never use them directly, use sk_<type>_... instead */
 #define SKM_sk_new(type, cmp) \
-       ((STACK_OF(type) * (*)(int (*)(const type * const *, const type * const *)))openssl_fcast(sk_new))(cmp)
+       ((STACK_OF(type) *)sk_new(CHECKED_SK_CMP_FUNC(type, cmp)))
 #define SKM_sk_new_null(type) \
-       ((STACK_OF(type) * (*)(void))openssl_fcast(sk_new_null))()
+       ((STACK_OF(type) *)sk_new_null())
 #define SKM_sk_free(type, st) \
-       ((void (*)(STACK_OF(type) *))openssl_fcast(sk_free))(st)
+       sk_free(CHECKED_PTR_OF(STACK_OF(type), st))
 #define SKM_sk_num(type, st) \
-       ((int (*)(const STACK_OF(type) *))openssl_fcast(sk_num))(st)
+       sk_num(CHECKED_PTR_OF(STACK_OF(type), st))
 #define SKM_sk_value(type, st,i) \
-       ((type * (*)(const STACK_OF(type) *, int))openssl_fcast(sk_value))(st, i)
+       ((type *)sk_value(CHECKED_PTR_OF(STACK_OF(type), st), i))
 #define SKM_sk_set(type, st,i,val) \
-       ((type * (*)(STACK_OF(type) *, int, type *))openssl_fcast(sk_set))(st, i, val)
+       sk_set(CHECKED_PTR_OF(STACK_OF(type), st), i, CHECKED_PTR_OF(type, val))
 #define SKM_sk_zero(type, st) \
-       ((void (*)(STACK_OF(type) *))openssl_fcast(sk_zero))(st)
+       sk_zero(CHECKED_PTR_OF(STACK_OF(type), st))
 #define SKM_sk_push(type, st,val) \
-       ((int (*)(STACK_OF(type) *, type *))openssl_fcast(sk_push))(st, val)
+       sk_push(CHECKED_PTR_OF(STACK_OF(type), st), CHECKED_PTR_OF(type, val))
 #define SKM_sk_unshift(type, st,val) \
-       ((int (*)(STACK_OF(type) *, type *))openssl_fcast(sk_unshift))(st, val)
+       sk_unshift(CHECKED_PTR_OF(STACK_OF(type), st), CHECKED_PTR_OF(type, val))
 #define SKM_sk_find(type, st,val) \
-       ((int (*)(STACK_OF(type) *, type *))openssl_fcast(sk_find))(st, val)
+       sk_find(CHECKED_PTR_OF(STACK_OF(type), st), CHECKED_PTR_OF(type, val))
 #define SKM_sk_delete(type, st,i) \
-       ((type * (*)(STACK_OF(type) *, int))openssl_fcast(sk_delete))(st, i)
+       (type *)sk_delete(CHECKED_PTR_OF(STACK_OF(type), st), i)
 #define SKM_sk_delete_ptr(type, st,ptr) \
-       ((type * (*)(STACK_OF(type) *, type *))openssl_fcast(sk_delete_ptr))(st, ptr)
+       (type *)sk_delete_ptr(CHECKED_PTR_OF(STACK_OF(type), st), CHECKED_PTR_OF(type, ptr))
 #define SKM_sk_insert(type, st,val,i) \
-       ((int (*)(STACK_OF(type) *, type *, int))openssl_fcast(sk_insert))(st, val, i)
+       sk_insert(CHECKED_PTR_OF(STACK_OF(type), st), CHECKED_PTR_OF(type, val), i)
 #define SKM_sk_set_cmp_func(type, st,cmp) \
-       ((int (*(*)(STACK_OF(type) *, int (*)(const type * const *, const type * const *))) \
-         (const type * const *, const type * const *))openssl_fcast(sk_set_cmp_func))\
-       (st, cmp)
+       ((int (*)(const type * const *,const type * const *)) \
+       sk_set_cmp_func(CHECKED_PTR_OF(STACK_OF(type), st), CHECKED_SK_CMP_FUNC(type, cmp)))
 #define SKM_sk_dup(type, st) \
-       ((STACK_OF(type) *(*)(STACK_OF(type) *))openssl_fcast(sk_dup))(st)
+       (STACK_OF(type) *)sk_dup(CHECKED_PTR_OF(STACK_OF(type), st))
 #define SKM_sk_pop_free(type, st,free_func) \
-       ((void (*)(STACK_OF(type) *, void (*)(type *)))openssl_fcast(sk_pop_free))\
-       (st, free_func)
+       sk_pop_free(CHECKED_PTR_OF(STACK_OF(type), st), CHECKED_SK_FREE_FUNC(type, free_func))
 #define SKM_sk_shift(type, st) \
-       ((type * (*)(STACK_OF(type) *))openssl_fcast(sk_shift))(st)
+       (type *)sk_shift(CHECKED_PTR_OF(STACK_OF(type), st))
 #define SKM_sk_pop(type, st) \
-       ((type * (*)(STACK_OF(type) *))openssl_fcast(sk_pop))(st)
+       (type *)sk_pop(CHECKED_PTR_OF(STACK_OF(type), st))
 #define SKM_sk_sort(type, st) \
-       ((void (*)(STACK_OF(type) *))openssl_fcast(sk_sort))(st)
+       sk_sort(CHECKED_PTR_OF(STACK_OF(type), st))
 #define SKM_sk_is_sorted(type, st) \
-       ((int (*)(const STACK_OF(type) *))openssl_fcast(sk_is_sorted))(st)
+       sk_is_sorted(CHECKED_PTR_OF(STACK_OF(type), st))
 
 #define        SKM_ASN1_SET_OF_d2i(type, st, pp, length, d2i_func, free_func, ex_tag, ex_class) \
-((STACK_OF(type) * (*) (STACK_OF(type) **,const unsigned char **, long , \
-                         type *(*)(type **, const unsigned char **,long), \
-                                void (*)(type *), int ,int )) openssl_fcast(d2i_ASN1_SET)) \
-                       (st,pp,length, d2i_func, free_func, ex_tag,ex_class)
+       (STACK_OF(type) *)d2i_ASN1_SET(CHECKED_PTR_OF(STACK_OF(type), st), \
+                               pp, length, \
+                               CHECKED_D2I_OF(type, d2i_func), \
+                               CHECKED_SK_FREE_FUNC(type, free_func), \
+                               ex_tag, ex_class)
+
 #define        SKM_ASN1_SET_OF_i2d(type, st, pp, i2d_func, ex_tag, ex_class, is_set) \
-       ((int (*)(STACK_OF(type) *,unsigned char **, \
-        int (*)(type *,unsigned char **), int , int , int)) openssl_fcast(i2d_ASN1_SET)) \
-                                               (st,pp,i2d_func,ex_tag,ex_class,is_set)
+       i2d_ASN1_SET(CHECKED_PTR_OF(STACK_OF(type), st), pp, \
+                               CHECKED_I2D_OF(type, i2d_func), \
+                               ex_tag, ex_class, is_set)
 
 #define        SKM_ASN1_seq_pack(type, st, i2d_func, buf, len) \
-       ((unsigned char *(*)(STACK_OF(type) *, \
-        int (*)(type *,unsigned char **), unsigned char **,int *)) openssl_fcast(ASN1_seq_pack)) \
-                               (st, i2d_func, buf, len)
+       ASN1_seq_pack(CHECKED_PTR_OF(STACK_OF(type), st), \
+                       CHECKED_I2D_OF(type, i2d_func), buf, len)
+
 #define        SKM_ASN1_seq_unpack(type, buf, len, d2i_func, free_func) \
-       ((STACK_OF(type) * (*)(const unsigned char *,int, \
-                              type *(*)(type **,const unsigned char **, long), \
-                              void (*)(type *)))openssl_fcast(ASN1_seq_unpack)) \
-                                       (buf,len,d2i_func, free_func)
+       (STACK_OF(type) *)ASN1_seq_unpack(buf, len, CHECKED_D2I_OF(type, d2i_func), CHECKED_SK_FREE_FUNC(type, free_func))
 
 #define SKM_PKCS12_decrypt_d2i(type, algor, d2i_func, free_func, pass, passlen, oct, seq) \
-       ((STACK_OF(type) * (*)(X509_ALGOR *, \
-                       type *(*)(type **, const unsigned char **, long), \
-                               void (*)(type *), \
-                                const char *, int, \
-                                ASN1_STRING *, int))PKCS12_decrypt_d2i) \
-                               (algor,d2i_func,free_func,pass,passlen,oct,seq)
+       (STACK_OF(type) *)PKCS12_decrypt_d2i(algor, \
+                               CHECKED_D2I_OF(type, d2i_func), \
+                               CHECKED_SK_FREE_FUNC(type, free_func), \
+                               pass, passlen, oct, seq)
 
 #else
 
@@ -960,6 +964,28 @@ STACK_OF(type) \
 #define sk_OCSP_ONEREQ_sort(st) SKM_sk_sort(OCSP_ONEREQ, (st))
 #define sk_OCSP_ONEREQ_is_sorted(st) SKM_sk_is_sorted(OCSP_ONEREQ, (st))
 
+#define sk_OCSP_RESPID_new(st) SKM_sk_new(OCSP_RESPID, (st))
+#define sk_OCSP_RESPID_new_null() SKM_sk_new_null(OCSP_RESPID)
+#define sk_OCSP_RESPID_free(st) SKM_sk_free(OCSP_RESPID, (st))
+#define sk_OCSP_RESPID_num(st) SKM_sk_num(OCSP_RESPID, (st))
+#define sk_OCSP_RESPID_value(st, i) SKM_sk_value(OCSP_RESPID, (st), (i))
+#define sk_OCSP_RESPID_set(st, i, val) SKM_sk_set(OCSP_RESPID, (st), (i), (val))
+#define sk_OCSP_RESPID_zero(st) SKM_sk_zero(OCSP_RESPID, (st))
+#define sk_OCSP_RESPID_push(st, val) SKM_sk_push(OCSP_RESPID, (st), (val))
+#define sk_OCSP_RESPID_unshift(st, val) SKM_sk_unshift(OCSP_RESPID, (st), (val))
+#define sk_OCSP_RESPID_find(st, val) SKM_sk_find(OCSP_RESPID, (st), (val))
+#define sk_OCSP_RESPID_find_ex(st, val) SKM_sk_find_ex(OCSP_RESPID, (st), (val))
+#define sk_OCSP_RESPID_delete(st, i) SKM_sk_delete(OCSP_RESPID, (st), (i))
+#define sk_OCSP_RESPID_delete_ptr(st, ptr) SKM_sk_delete_ptr(OCSP_RESPID, (st), (ptr))
+#define sk_OCSP_RESPID_insert(st, val, i) SKM_sk_insert(OCSP_RESPID, (st), (val), (i))
+#define sk_OCSP_RESPID_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(OCSP_RESPID, (st), (cmp))
+#define sk_OCSP_RESPID_dup(st) SKM_sk_dup(OCSP_RESPID, st)
+#define sk_OCSP_RESPID_pop_free(st, free_func) SKM_sk_pop_free(OCSP_RESPID, (st), (free_func))
+#define sk_OCSP_RESPID_shift(st) SKM_sk_shift(OCSP_RESPID, (st))
+#define sk_OCSP_RESPID_pop(st) SKM_sk_pop(OCSP_RESPID, (st))
+#define sk_OCSP_RESPID_sort(st) SKM_sk_sort(OCSP_RESPID, (st))
+#define sk_OCSP_RESPID_is_sorted(st) SKM_sk_is_sorted(OCSP_RESPID, (st))
+
 #define sk_OCSP_SINGLERESP_new(st) SKM_sk_new(OCSP_SINGLERESP, (st))
 #define sk_OCSP_SINGLERESP_new_null() SKM_sk_new_null(OCSP_SINGLERESP)
 #define sk_OCSP_SINGLERESP_free(st) SKM_sk_free(OCSP_SINGLERESP, (st))
index 16a954f709941a57224a2b621c543831927cf60d..c431237ec7e94aaa3e6389b86667cefefbf0d62d 100644 (file)
@@ -203,6 +203,8 @@ typedef struct X509_extension_st
        ASN1_OCTET_STRING *value;
        } X509_EXTENSION;
 
+typedef STACK_OF(X509_EXTENSION) X509_EXTENSIONS;
+
 DECLARE_STACK_OF(X509_EXTENSION)
 DECLARE_ASN1_SET_OF(X509_EXTENSION)
 
@@ -918,6 +920,7 @@ DECLARE_ASN1_FUNCTIONS(X509_ATTRIBUTE)
 X509_ATTRIBUTE *X509_ATTRIBUTE_create(int nid, int atrtype, void *value);
 
 DECLARE_ASN1_FUNCTIONS(X509_EXTENSION)
+DECLARE_ASN1_ENCODE_FUNCTIONS(X509_EXTENSIONS, X509_EXTENSIONS, X509_EXTENSIONS)
 
 DECLARE_ASN1_FUNCTIONS(X509_NAME_ENTRY)
 
index 07df21f6b975a0e921f291dae166d4df7ab347d5..9a62ebcf679e5349532294b8cbbfdc974d2c99c8 100644 (file)
@@ -164,7 +164,7 @@ int X509_verify_cert(X509_STORE_CTX *ctx)
                                        goto end;
                                        }
                                CRYPTO_add(&xtmp->references,1,CRYPTO_LOCK_X509);
-                               sk_X509_delete_ptr(sktmp,xtmp);
+                               (void)sk_X509_delete_ptr(sktmp,xtmp);
                                ctx->last_untrusted++;
                                x=xtmp;
                                num++;
@@ -214,7 +214,7 @@ int X509_verify_cert(X509_STORE_CTX *ctx)
                                 */
                                X509_free(x);
                                x = xtmp;
-                               sk_X509_set(ctx->chain, i - 1, x);
+                               (void)sk_X509_set(ctx->chain, i - 1, x);
                                ctx->last_untrusted=0;
                                }
                        }
index 5e69259a7934b40c9656a84f475c3c5118a1abc7..e9db6d62a74984ca0ac241af2b7f13e350d02392 100644 (file)
@@ -385,7 +385,7 @@ int X509_VERIFY_PARAM_add0_table(X509_VERIFY_PARAM *param)
                        {
                        ptmp = sk_X509_VERIFY_PARAM_value(param_table, idx);
                        X509_VERIFY_PARAM_free(ptmp);
-                       sk_X509_VERIFY_PARAM_delete(param_table, idx);
+                       (void)sk_X509_VERIFY_PARAM_delete(param_table, idx);
                        }
                }
        if (!sk_X509_VERIFY_PARAM_push(param_table, param))
index 27d29f25a84e7733f94a3b08b01300f6c9943f4d..4fda1d419af6da9488b7a952eedd60920265e8c1 100644 (file)
@@ -345,7 +345,7 @@ static int tree_prune(X509_POLICY_TREE *tree, X509_POLICY_LEVEL *curr)
                        {
                        node->parent->nchild--;
                        OPENSSL_free(node);
-                       sk_X509_POLICY_NODE_delete(curr->nodes, i);
+                       (void)sk_X509_POLICY_NODE_delete(curr->nodes, i);
                        }
                }
 
@@ -358,7 +358,7 @@ static int tree_prune(X509_POLICY_TREE *tree, X509_POLICY_LEVEL *curr)
                                {
                                node->parent->nchild--;
                                OPENSSL_free(node);
-                               sk_X509_POLICY_NODE_delete(curr->nodes, i);
+                               (void)sk_X509_POLICY_NODE_delete(curr->nodes, i);
                                }
                        }
                if (curr->anyPolicy && !curr->anyPolicy->nchild)
index 3dba0557b86d87bb77d274c7a381af7f9b5638ac..ac171ca940a3cb6d721797f79cafde5d3d587266 100644 (file)
@@ -473,6 +473,30 @@ STACK *X509_get1_email(X509 *x)
        return ret;
 }
 
+STACK *X509_get1_ocsp(X509 *x)
+{
+       AUTHORITY_INFO_ACCESS *info;
+       STACK *ret = NULL;
+       int i;
+       info = X509_get_ext_d2i(x, NID_info_access, NULL, NULL);
+       if (!info)
+               return NULL;
+       for (i = 0; i < sk_ACCESS_DESCRIPTION_num(info); i++)
+               {
+               ACCESS_DESCRIPTION *ad = sk_ACCESS_DESCRIPTION_value(info, i);
+               if (OBJ_obj2nid(ad->method) == NID_ad_OCSP)
+                       {
+                       if (ad->location->type == GEN_URI)
+                               {
+                               if (!append_ia5(&ret, ad->location->d.uniformResourceIdentifier))
+                                       break;
+                               }
+                       }
+               }
+       AUTHORITY_INFO_ACCESS_free(info);
+       return ret;
+}
+
 STACK *X509_REQ_get1_email(X509_REQ *x)
 {
        GENERAL_NAMES *gens;
index 91d2fb5b8baf6c3469bee022b985ff0f8930d318..db2b0482c152e57fcc1749ca097ab053f82bdb1a 100644 (file)
@@ -617,6 +617,7 @@ int X509_PURPOSE_get_id(X509_PURPOSE *);
 STACK *X509_get1_email(X509 *x);
 STACK *X509_REQ_get1_email(X509_REQ *x);
 void X509_email_free(STACK *sk);
+STACK *X509_get1_ocsp(X509 *x);
 
 ASN1_OCTET_STRING *a2i_IPADDRESS(const char *ipasc);
 ASN1_OCTET_STRING *a2i_IPADDRESS_NC(const char *ipasc);
index c17a83a225812c2b21fade7e58a84291e7fa00d5..c44d357cf754a2260d2564b434c86df8b54e24d5 100644 (file)
@@ -38,6 +38,10 @@ B<openssl> B<s_client>
 [B<-cipher cipherlist>]
 [B<-starttls protocol>]
 [B<-engine id>]
+[B<-tlsextdebug>]
+[B<-no_ticket>]
+[B<-sess_out filename>]
+[B<-sess_in filename>]
 [B<-rand file(s)>]
 
 =head1 DESCRIPTION
@@ -186,6 +190,26 @@ send the protocol-specific message(s) to switch to TLS for communication.
 B<protocol> is a keyword for the intended protocol.  Currently, the only
 supported keywords are "smtp", "pop3", "imap", and "ftp".
 
+=item B<-tlsextdebug>
+
+print out a hex dump of any TLS extensions received from the server. Note: this
+option is only available if extension support is explicitly enabled at compile
+time
+
+=item B<-no_ticket>
+
+disable RFC4507bis session ticket support. Note: this option is only available
+if extension support is explicitly enabled at compile time
+
+=item B<-sess_out filename>
+
+output SSL session to B<filename>
+
+=item B<-sess_in sess.pem>
+
+load SSL session from B<filename>. The client will attempt to resume a
+connection from this session.
+
 =item B<-engine id>
 
 specifying an engine (by it's unique B<id> string) will cause B<s_client>
@@ -246,6 +270,13 @@ on the command line is no guarantee that the certificate works.
 If there are problems verifying a server certificate then the
 B<-showcerts> option can be used to show the whole chain.
 
+Since the SSLv23 client hello cannot include compression methods or extensions
+these will only be supported if its use is disabled, for example by using the
+B<-no_sslv2> option.
+
+TLS extensions are only supported in OpenSSL 0.9.8 if they are explictly
+enabled at compile time using for example the B<enable-tlsext> switch.
+
 =head1 BUGS
 
 Because this program has a lot of options and also because some of
index 7c1a9581d9619f52a5f8a693c03cd20f9c7f41e6..57c2adfb9f9da88e5000d08ee665918ab26f6488 100644 (file)
@@ -48,6 +48,8 @@ B<openssl> B<s_server>
 [B<-WWW>]
 [B<-HTTP>]
 [B<-engine id>]
+[B<-tlsextdebug>]
+[B<-no_ticket>]
 [B<-id_prefix arg>]
 [B<-rand file(s)>]
 
@@ -205,6 +207,14 @@ also included in the server list is used. Because the client specifies
 the preference order, the order of the server cipherlist irrelevant. See
 the B<ciphers> command for more information.
 
+=item B<-tlsextdebug>
+
+print out a hex dump of any TLS extensions received from the server.
+
+=item B<-no_ticket>
+
+disable RFC4507bis session ticket support. 
+
 =item B<-www>
 
 sends a status message back to the client when it connects. This includes
@@ -307,6 +317,9 @@ mean any CA is acceptable. This is useful for debugging purposes.
 
 The session parameters can printed out using the B<sess_id> program.
 
+TLS extensions are only supported in OpenSSL 0.9.8 if they are explictly
+enabled at compile time using for example the B<enable-tlsext> switch.
+
 =head1 BUGS
 
 Because this program has a lot of options and also because some of
index ba6e3c2e81401a375c8c99c8535ad9185fe160c1..60867d951acb433b437fe736af7d0396bcbd71de 100644 (file)
@@ -28,7 +28,11 @@ The actual data encoded is determined by the string B<str> and
 the configuration information. The general format of the string
 is:
 
- B<[modifier,]type[:value]>
+=over 2
+
+=item B<[modifier,]type[:value]>
+
+=back
 
 That is zero or more comma separated modifiers followed by a type
 followed by an optional colon and a value. The formats of B<type>,
@@ -81,13 +85,13 @@ the format B<YYYYMMDDHHMMSSZ>.
 
 =item B<OCTETSTRING>, B<OCT>
 
-Emcodes an ASN1 B<OCTET STRING>. B<value> represents the contents
+Encodes an ASN1 B<OCTET STRING>. B<value> represents the contents
 of this structure, the format strings B<ASCII> and B<HEX> can be
 used to specify the format of B<value>.
 
-=item B<BITSRING>, B<BITSTR>
+=item B<BITSTRING>, B<BITSTR>
 
-Emcodes an ASN1 B<BIT STRING>. B<value> represents the contents
+Encodes an ASN1 B<BIT STRING>. B<value> represents the contents
 of this structure, the format strings B<ASCII>, B<HEX> and B<BITLIST>
 can be used to specify the format of B<value>.
 
@@ -171,13 +175,13 @@ An IA5String explicitly tagged using APPLICATION tagging:
 A more complex example using a config file to produce a
 SEQUENCE consiting of a BOOL an OID and a UTF8String:
 
-asn1 = SEQUENCE:seq_section
+ asn1 = SEQUENCE:seq_section
 
-[seq_section]
+ [seq_section]
 
-field1 = BOOLEAN:TRUE
-field2 = OID:commonName
-field3 = UTF8:Third field
+ field1 = BOOLEAN:TRUE
+ field2 = OID:commonName
+ field3 = UTF8:Third field
 
 This example produces an RSAPrivateKey structure, this is the
 key contained in the file client.pem in all OpenSSL distributions
index 73261fc4675ddaeb4e0955fe17bdda840678f478..d5cdc3be0ce6ac54b420536f9cc3f2264fe63284 100644 (file)
@@ -36,7 +36,7 @@ structures created later. B<NB>: This is true only whilst no ENGINE has been set
 as a default for DH, so this function is no longer recommended.
 
 DH_get_default_method() returns a pointer to the current default DH_METHOD.
-However, the meaningfulness of this result is dependant on whether the ENGINE
+However, the meaningfulness of this result is dependent on whether the ENGINE
 API is being used, so this function is no longer recommended.
 
 DH_set_method() selects B<meth> to perform all operations using the key B<dh>.
index bc3cfb1f0a78d419d79fd43cabd7a84f577194f3..9c1434bd8d429630e6ac2534fa3fcc86c5db5413 100644 (file)
@@ -36,7 +36,7 @@ structures created later. B<NB>: This is true only whilst no ENGINE has
 been set as a default for DSA, so this function is no longer recommended.
 
 DSA_get_default_method() returns a pointer to the current default
-DSA_METHOD. However, the meaningfulness of this result is dependant on
+DSA_METHOD. However, the meaningfulness of this result is dependent on
 whether the ENGINE API is being used, so this function is no longer 
 recommended.
 
index 121a8ddee5e1f48ef3a442dba186b1a143009b4f..2e659d34a5c43b29e36b2e622a30fd165c99aa1f 100644 (file)
@@ -17,19 +17,27 @@ register after executing CPUID instruction with EAX=1 input value (see
 Intel Application Note #241618). Naturally it's meaningful on IA-32[E]
 platforms only. The variable is normally set up automatically upon
 toolkit initialization, but can be manipulated afterwards to modify
-crypto library behaviour. For the moment of this writing three bits are
-significant, namely bit #28 denoting Hyperthreading, which is used to
-distinguish Intel P4 core, bit #26 denoting SSE2 support, and bit #4
-denoting presence of Time-Stamp Counter. Clearing bit #26 at run-time
-for example disables high-performance SSE2 code present in the crypto
-library. You might have to do this if target OpenSSL application is
-executed on SSE2 capable CPU, but under control of OS which does not
-support SSE2 extentions. Even though you can manipulate the value
-programmatically, you most likely will find it more appropriate to set
-up an environment variable with the same name prior starting target
-application, e.g. 'env OPENSSL_ia32cap=0x10 apps/openssl', to achieve
-same effect without modifying the application source code.
-Alternatively you can reconfigure the toolkit with no-sse2 option and
-recompile.
+crypto library behaviour. For the moment of this writing six bits are
+significant, namely:
+
+1. bit #28 denoting Hyperthreading, which is used to distiguish
+   cores with shared cache;
+2. bit #26 denoting SSE2 support;
+3. bit #25 denoting SSE support;
+4. bit #23 denoting MMX support;
+5. bit #20, reserved by Intel, is used to choose between RC4 code
+   pathes;
+6. bit #4 denoting presence of Time-Stamp Counter.
+
+For example, clearing bit #26 at run-time disables high-performance
+SSE2 code present in the crypto library. You might have to do this if
+target OpenSSL application is executed on SSE2 capable CPU, but under
+control of OS which does not support SSE2 extentions. Even though you
+can manipulate the value programmatically, you most likely will find it
+more appropriate to set up an environment variable with the same name
+prior starting target application, e.g. on Intel P4 processor 'env
+OPENSSL_ia32cap=0x12900010 apps/openssl', to achieve same effect
+without modifying the application source code. Alternatively you can
+reconfigure the toolkit with no-sse2 option and recompile.
 
 =cut
index ce6329ce54afe2a9ffe95b15d3448864b8b5a636..1a9b91e28144222419516b99392b3222c50d865b 100644 (file)
@@ -25,6 +25,9 @@ unpredictable. They can be used for non-cryptographic purposes and for
 certain purposes in cryptographic protocols, but usually not for key
 generation etc.
 
+The contents of B<buf> is mixed into the entropy pool before retrieving
+the new pseudo-random bytes unless disabled at compile time (see FAQ).
+
 =head1 RETURN VALUES
 
 RAND_bytes() returns 1 on success, 0 otherwise. The error code can be
index c9bb6d9f27b3f0f67bebc2ce7d61e3dadacf2c7b..e5b780fad06b5a441a6c8928e596249af0dfad01 100644 (file)
@@ -30,7 +30,7 @@ true only whilst no ENGINE has been set as a default for RAND, so this function
 is no longer recommended.
 
 RAND_get_default_method() returns a pointer to the current RAND_METHOD.
-However, the meaningfulness of this result is dependant on whether the ENGINE
+However, the meaningfulness of this result is dependent on whether the ENGINE
 API is being used, so this function is no longer recommended.
 
 =head1 THE RAND_METHOD STRUCTURE
index 0a305f6b140d4279aa9afc49486f4465b5c7dd07..2c963d7e5bbaa0989b2572591122e26f91b4c79e 100644 (file)
@@ -42,7 +42,7 @@ structures created later. B<NB>: This is true only whilst no ENGINE has
 been set as a default for RSA, so this function is no longer recommended.
 
 RSA_get_default_method() returns a pointer to the current default
-RSA_METHOD. However, the meaningfulness of this result is dependant on
+RSA_METHOD. However, the meaningfulness of this result is dependent on
 whether the ENGINE API is being used, so this function is no longer 
 recommended.
 
index 919b90891937f9f6cd6c642ab596203d32131117..2579a5dc9dc6fa32c4a13c55027257f7eab21b47 100644 (file)
@@ -86,10 +86,10 @@ is equivalent to:
  B<ASN1_STRFLGS_RFC2253 | XN_FLAG_SEP_COMMA_PLUS | XN_FLAG_DN_REV | XN_FLAG_FN_SN | XN_FLAG_DUMP_UNKNOWN_FIELDS>
 
 
-B<XN_FLAG_ONELINE> is a more readable one line format it is the same as:
+B<XN_FLAG_ONELINE> is a more readable one line format which is the same as:
  B<ASN1_STRFLGS_RFC2253 | ASN1_STRFLGS_ESC_QUOTE | XN_FLAG_SEP_CPLUS_SPC | XN_FLAG_SPC_EQ | XN_FLAG_FN_SN>
 
-B<XN_FLAG_MULTILINE> is a multiline format is is the same as:
+B<XN_FLAG_MULTILINE> is a multiline format which is the same as:
  B<ASN1_STRFLGS_ESC_CTRL | ASN1_STRFLGS_ESC_MSB | XN_FLAG_SEP_MULTILINE | XN_FLAG_SPC_EQ | XN_FLAG_FN_LN | XN_FLAG_FN_ALIGN>
 
 B<XN_FLAG_COMPAT> uses a format identical to X509_NAME_print(): in fact it calls X509_NAME_print() internally.
index 75933fccadc50b5ae669291204a1c3cd53f7386e..f5ab1c3e50fd73476ec00ab7ede508d24aaaf94e 100644 (file)
@@ -183,7 +183,7 @@ Due to the modular nature of the ENGINE API, pointers to ENGINEs need to be
 treated as handles - ie. not only as pointers, but also as references to
 the underlying ENGINE object. Ie. one should obtain a new reference when
 making copies of an ENGINE pointer if the copies will be used (and
-released) independantly.
+released) independently.
 
 ENGINE objects have two levels of reference-counting to match the way in
 which the objects are used. At the most basic level, each ENGINE pointer is
@@ -200,7 +200,7 @@ B<functional> reference. This kind of reference can be considered a
 specialised form of structural reference, because each functional reference
 implicitly contains a structural reference as well - however to avoid
 difficult-to-find programming bugs, it is recommended to treat the two
-kinds of reference independantly. If you have a functional reference to an
+kinds of reference independently. If you have a functional reference to an
 ENGINE, you have a guarantee that the ENGINE has been initialised ready to
 perform cryptographic operations and will remain uninitialised
 until after you have released your reference.
@@ -587,7 +587,7 @@ extension).
 The ENGINE API and internal architecture is currently being reviewed. Slated for
 possible release in 0.9.8 is support for transparent loading of "dynamic"
 ENGINEs (built as self-contained shared-libraries). This would allow ENGINE
-implementations to be provided independantly of OpenSSL libraries and/or
+implementations to be provided independently of OpenSSL libraries and/or
 OpenSSL-based applications, and would also remove any requirement for
 applications to explicitly use the "dynamic" ENGINE to bind to shared-library
 implementations.
index fa63263601c8294716f17a9f5b8143504ef5831f..eaed1908097516687c1d0e4f2e95a45116c50b10 100644 (file)
@@ -201,6 +201,15 @@ When performing renegotiation as a server, always start a new session
 (i.e., session resumption requests are only accepted in the initial
 handshake).  This option is not needed for clients.
 
+=item SSL_OP_NO_TICKET
+
+Normally clients and servers will, where possible, transparently make use
+of RFC4507bis tickets for stateless session resumption if extension support
+is explicitly set when OpenSSL is compiled.
+
+If this option is set this functionality is disabled and tickets will
+not be used by clients or servers.
+
 =back
 
 =head1 RETURN VALUES
diff --git a/e_os.h b/e_os.h
index 5068d1bd74feaa3acef2e73736937be7a97b8f7e..ab3c539eab869ede1bb2b075f948d38d27dada76 100644 (file)
--- a/e_os.h
+++ b/e_os.h
@@ -277,6 +277,14 @@ static unsigned int _strlen31(const char *str)
        }
 #    endif
 #    include <malloc.h>
+#    if defined(_MSC_VER) && _MSC_VER<=1200 && defined(_MT) && defined(isspace)
+       /* compensate for bug is VC6 ctype.h */
+#      undef isspace
+#      undef isdigit
+#      undef isalnum
+#      undef isupper
+#      undef isxdigit
+#    endif
 #  endif
 #  include <io.h>
 #  include <fcntl.h>
index 39da65f74bf136428e3da8fd903e2fef2979da2a..f7126d8621182422109c11d0ebe5711c0f01f784 100644 (file)
  */
 
 /* This engine is not (currently) compiled in by default. Do enable it,
- * reconfigure OpenSSL with "-DOPENSSL_USE_GMP -lgmp". The GMP libraries and
+ * reconfigure OpenSSL with "enable-gmp -lgmp". The GMP libraries and
  * headers must reside in one of the paths searched by the compiler/linker,
  * otherwise paths must be specified - eg. try configuring with
- * "-DOPENSSL_USE_GMP -I<includepath> -L<libpath> -lgmp". YMMV. */
+ * "enable-gmp -I<includepath> -L<libpath> -lgmp". YMMV. */
 
 /* As for what this does - it's a largely unoptimised implementation of an
  * ENGINE that uses the GMP library to perform RSA private key operations. To
@@ -87,7 +87,7 @@
 #include <openssl/engine.h>
 
 #ifndef OPENSSL_NO_HW
-#if defined(OPENSSL_USE_GMP) && !defined(OPENSSL_NO_HW_GMP)
+#ifndef OPENSSL_NO_GMP
 
 #include <gmp.h>
 
@@ -417,7 +417,7 @@ static int e_gmp_rsa_mod_exp(BIGNUM *r, const BIGNUM *I, RSA *rsa, BN_CTX *ctx)
 
 /* This stuff is needed if this ENGINE is being compiled into a self-contained
  * shared-library. */     
-#ifdef ENGINE_DYNAMIC_SUPPORT
+#ifndef ENGINE_NO_DYNAMIC_SUPPORT
 static int bind_fn(ENGINE *e, const char *id)
        {
        if(id && (strcmp(id, engine_e_gmp_id) != 0))
@@ -430,6 +430,6 @@ IMPLEMENT_DYNAMIC_CHECK_FN()
 IMPLEMENT_DYNAMIC_BIND_FN(bind_fn)
 #endif /* ENGINE_DYNAMIC_SUPPORT */
 
-#endif /* !OPENSSL_NO_HW_GMP */
+#endif /* !OPENSSL_NO_GMP */
 #endif /* !OPENSSL_NO_HW */
 
index 8b6c98bafa20b47ef09928450ddc2b2d5bc6c451..e8389de6a1f85ed8b5ca1d65a5a75049e3bc0fd1 100644 (file)
@@ -822,11 +822,11 @@ static int ubsec_dsa_verify(const unsigned char *dgst, int dgst_len,
        int v_len, d_len;
        int to_return = 0;
        int fd;
-       BIGNUM v;
+       BIGNUM v, *pv = &v;
 
        BN_init(&v);
 
-       if(!bn_wexpand(&v, dsa->p->top)) {
+       if(!bn_wexpand(pv, dsa->p->top)) {
                UBSECerr(UBSEC_F_UBSEC_DSA_VERIFY, UBSEC_R_BN_EXPAND_FAIL);
                goto err;
        }
index 284ff87ccbafc0875951b60f90608cc5da098ce1..2b2173bf4a10fa3357834b3b3babc6bc77827dc3 100755 (executable)
@@ -317,7 +317,12 @@ $   WRITE H_FILE "#define THIRTY_TWO_BIT"
 $   WRITE H_FILE "#undef SIXTEEN_BIT"
 $   WRITE H_FILE "#undef EIGHT_BIT"
 $   WRITE H_FILE "#endif"
-$
+$!
+$   WRITE H_FILE "#if defined(HEADER_SHA_H)"
+$   WRITE H_FILE "#undef OPENSSL_NO_SHA512"
+$   WRITE H_FILE "#define OPENSSL_NO_SHA512"
+$   WRITE H_FILE "#endif"
+$!
 $   WRITE H_FILE "#undef OPENSSL_EXPORT_VAR_AS_FUNCTION"
 $   WRITE H_FILE "#define OPENSSL_EXPORT_VAR_AS_FUNCTION"
 $!
index 7e6d300377ac383c116c5e064e9ab65a08f84ff8..15a201a25cf4f36a16cfdab91c7f31459414a8b4 100644 (file)
@@ -138,38 +138,40 @@ static void dtls1_set_message_header_int(SSL *s, unsigned char mt,
        unsigned long frag_len);
 static int dtls1_retransmit_buffered_messages(SSL *s);
 static long dtls1_get_message_fragment(SSL *s, int st1, int stn, 
-    long max, int *ok);
-static void dtls1_process_handshake_fragment(SSL *s, int frag_len);
+       long max, int *ok);
 
 static hm_fragment *
 dtls1_hm_fragment_new(unsigned long frag_len)
-    {
-    hm_fragment *frag = NULL;
-    unsigned char *buf = NULL;
-
-    frag = (hm_fragment *)OPENSSL_malloc(sizeof(hm_fragment));
-    if ( frag == NULL)
-        return NULL;
-
-    buf = (unsigned char *)OPENSSL_malloc(frag_len 
-        + DTLS1_HM_HEADER_LENGTH);
-    if ( buf == NULL)
-        {
-        OPENSSL_free(frag);
-        return NULL;
-        }
-    
-    frag->fragment = buf;
-
-    return frag;
-    }
+       {
+       hm_fragment *frag = NULL;
+       unsigned char *buf = NULL;
+
+       frag = (hm_fragment *)OPENSSL_malloc(sizeof(hm_fragment));
+       if ( frag == NULL)
+               return NULL;
+
+       if (frag_len)
+               {
+               buf = (unsigned char *)OPENSSL_malloc(frag_len);
+               if ( buf == NULL)
+                       {
+                       OPENSSL_free(frag);
+                       return NULL;
+                       }
+               }
+
+       /* zero length fragment gets zero frag->fragment */
+       frag->fragment = buf;
+
+       return frag;
+       }
 
 static void
 dtls1_hm_fragment_free(hm_fragment *frag)
-    {
-    OPENSSL_free(frag->fragment);
-    OPENSSL_free(frag);
-    }
+       {
+       if (frag->fragment) OPENSSL_free(frag->fragment);
+       OPENSSL_free(frag);
+       }
 
 /* send s->init_buf in records of type 'type' (SSL3_RT_HANDSHAKE or SSL3_RT_CHANGE_CIPHER_SPEC) */
 int dtls1_do_write(SSL *s, int type)
@@ -180,7 +182,7 @@ int dtls1_do_write(SSL *s, int type)
 
        /* AHA!  Figure out the MTU, and stick to the right size */
        if ( ! (SSL_get_options(s) & SSL_OP_NO_QUERY_MTU))
-        {
+               {
                s->d1->mtu = 
                        BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_QUERY_MTU, 0, NULL);
 
@@ -207,7 +209,7 @@ int dtls1_do_write(SSL *s, int type)
                mtu = curr_mtu;
        else if ( ( ret = BIO_flush(SSL_get_wbio(s))) <= 0)
                return ret;
-               
+
        if ( BIO_wpending(SSL_get_wbio(s)) + s->init_num >= mtu)
                {
                ret = BIO_flush(SSL_get_wbio(s));
@@ -254,11 +256,11 @@ int dtls1_do_write(SSL *s, int type)
                                s->init_off -= DTLS1_HM_HEADER_LENGTH;
                                s->init_num += DTLS1_HM_HEADER_LENGTH;
 
-                /* write atleast DTLS1_HM_HEADER_LENGTH bytes */
+                               /* write atleast DTLS1_HM_HEADER_LENGTH bytes */
                                if ( len <= DTLS1_HM_HEADER_LENGTH)  
                                        len += DTLS1_HM_HEADER_LENGTH;
                                }
-                       
+
                        dtls1_fix_message_header(s, frag_off, 
                                len - DTLS1_HM_HEADER_LENGTH);
 
@@ -286,18 +288,40 @@ int dtls1_do_write(SSL *s, int type)
                        }
                else
                        {
-                       
+
                        /* bad if this assert fails, only part of the handshake
                         * message got sent.  but why would this happen? */
-                       OPENSSL_assert(len == (unsigned int)ret); 
-                       
+                       OPENSSL_assert(len == (unsigned int)ret);
+
                        if (type == SSL3_RT_HANDSHAKE && ! s->d1->retransmitting)
+                               {
                                /* should not be done for 'Hello Request's, but in that case
                                 * we'll ignore the result anyway */
-                               ssl3_finish_mac(s, 
-                                       (unsigned char *)&s->init_buf->data[s->init_off + 
-                                               DTLS1_HM_HEADER_LENGTH], ret - DTLS1_HM_HEADER_LENGTH);
-                       
+                               unsigned char *p = (unsigned char *)&s->init_buf->data[s->init_off];
+                               const struct hm_header_st *msg_hdr = &s->d1->w_msg_hdr;
+                               int xlen;
+
+                               if (frag_off == 0 && s->client_version != DTLS1_BAD_VER)
+                                       {
+                                       /* reconstruct message header is if it
+                                        * is being sent in single fragment */
+                                       *p++ = msg_hdr->type;
+                                       l2n3(msg_hdr->msg_len,p);
+                                       s2n (msg_hdr->seq,p);
+                                       l2n3(0,p);
+                                       l2n3(msg_hdr->msg_len,p);
+                                       p  -= DTLS1_HM_HEADER_LENGTH;
+                                       xlen = ret;
+                                       }
+                               else
+                                       {
+                                       p  += DTLS1_HM_HEADER_LENGTH;
+                                       xlen = ret - DTLS1_HM_HEADER_LENGTH;
+                                       }
+
+                               ssl3_finish_mac(s, p, xlen);
+                               }
+
                        if (ret == s->init_num)
                                {
                                if (s->msg_callback)
@@ -307,7 +331,7 @@ int dtls1_do_write(SSL *s, int type)
 
                                s->init_off = 0;  /* done writing this message */
                                s->init_num = 0;
-                               
+
                                return(1);
                                }
                        s->init_off+=ret;
@@ -327,6 +351,7 @@ int dtls1_do_write(SSL *s, int type)
 long dtls1_get_message(SSL *s, int st1, int stn, int mt, long max, int *ok)
        {
        int i, al;
+       struct hm_header_st *msg_hdr;
 
        /* s3->tmp is used to store messages that are unexpected, caused
         * by the absence of an optional handshake message */
@@ -344,25 +369,56 @@ long dtls1_get_message(SSL *s, int st1, int stn, int mt, long max, int *ok)
                s->init_num = (int)s->s3->tmp.message_size;
                return s->init_num;
                }
-       
+
+       msg_hdr = &s->d1->r_msg_hdr;
        do
                {
-               if ( s->d1->r_msg_hdr.frag_off == 0)
+               if ( msg_hdr->frag_off == 0)
                        {
                        /* s->d1->r_message_header.msg_len = 0; */
-                       memset(&(s->d1->r_msg_hdr), 0x00, sizeof(struct hm_header_st));
+                       memset(msg_hdr, 0x00, sizeof(struct hm_header_st));
                        }
 
                i = dtls1_get_message_fragment(s, st1, stn, max, ok);
                if ( i == DTLS1_HM_BAD_FRAGMENT ||
-            i == DTLS1_HM_FRAGMENT_RETRY)  /* bad fragment received */
+                       i == DTLS1_HM_FRAGMENT_RETRY)  /* bad fragment received */
                        continue;
                else if ( i <= 0 && !*ok)
                        return i;
 
-               if (s->d1->r_msg_hdr.msg_len == (unsigned int)s->init_num - DTLS1_HM_HEADER_LENGTH)
+               /* Note that s->init_sum is used as a counter summing
+                * up fragments' lengths: as soon as they sum up to
+                * handshake packet length, we assume we have got all
+                * the fragments. Overlapping fragments would cause
+                * premature termination, so we don't expect overlaps.
+                * Well, handling overlaps would require something more
+                * drastic. Indeed, as it is now there is no way to
+                * tell if out-of-order fragment from the middle was
+                * the last. '>=' is the best/least we can do to control
+                * the potential damage caused by malformed overlaps. */
+               if ((unsigned int)s->init_num >= msg_hdr->msg_len)
                        {
-                       memset(&(s->d1->r_msg_hdr), 0x00, sizeof(struct hm_header_st));
+                       unsigned char *p = (unsigned char *)s->init_buf->data;
+                       unsigned long msg_len = msg_hdr->msg_len;
+
+                       /* reconstruct message header as if it was
+                        * sent in single fragment */
+                       *(p++) = msg_hdr->type;
+                       l2n3(msg_len,p);
+                       s2n (msg_hdr->seq,p);
+                       l2n3(0,p);
+                       l2n3(msg_len,p);
+                       if (s->client_version != DTLS1_BAD_VER)
+                               p       -= DTLS1_HM_HEADER_LENGTH,
+                               msg_len += DTLS1_HM_HEADER_LENGTH;
+
+                       ssl3_finish_mac(s, p, msg_len);
+                       if (s->msg_callback)
+                               s->msg_callback(0, s->version, SSL3_RT_HANDSHAKE,
+                                       p, msg_len,
+                                       s, s->msg_callback_arg);
+
+                       memset(msg_hdr, 0x00, sizeof(struct hm_header_st));
 
                        s->d1->handshake_read_seq++;
                        /* we just read a handshake message from the other side:
@@ -379,11 +435,11 @@ long dtls1_get_message(SSL *s, int st1, int stn, int mt, long max, int *ok)
                         * first data  segment, but is there a better way?  */
                        dtls1_clear_record_buffer(s);
 
-            s->init_msg = s->init_buf->data + DTLS1_HM_HEADER_LENGTH;
-                       return s->init_num - DTLS1_HM_HEADER_LENGTH;
+                       s->init_msg = s->init_buf->data + DTLS1_HM_HEADER_LENGTH;
+                       return s->init_num;
                        }
                else
-                       s->d1->r_msg_hdr.frag_off = i;
+                       msg_hdr->frag_off = i;
                } while(1) ;
 
 f_err:
@@ -393,161 +449,183 @@ f_err:
        }
 
 
-static int
-dtls1_retrieve_buffered_fragment(SSL *s, unsigned long *copied)
-    {
-    /* (0) check whether the desired fragment is available
-     * if so:
-     * (1) copy over the fragment to s->init_buf->data[]
-     * (2) update s->init_num
-     */
-    pitem *item;
-    hm_fragment *frag;
-    unsigned long overlap;
-    unsigned char *p;
-
-    item = pqueue_peek(s->d1->buffered_messages);
-    if ( item == NULL)
-        return 0;
-
-    frag = (hm_fragment *)item->data;
-    
-    if ( s->d1->handshake_read_seq == frag->msg_header.seq &&
-        frag->msg_header.frag_off <= (unsigned int)s->init_num - DTLS1_HM_HEADER_LENGTH)
-        {
-        pqueue_pop(s->d1->buffered_messages);
-        overlap = s->init_num - DTLS1_HM_HEADER_LENGTH 
-            - frag->msg_header.frag_off;
-
-        p = frag->fragment;
-
-        memcpy(&s->init_buf->data[s->init_num],
-            p + DTLS1_HM_HEADER_LENGTH + overlap,
-            frag->msg_header.frag_len - overlap);
-    
-        OPENSSL_free(frag->fragment);
-        OPENSSL_free(frag);
-        pitem_free(item);
-
-        *copied = frag->msg_header.frag_len - overlap;
-        return *copied;
-        }
-    else
-        return 0;
-    }
+static int dtls1_preprocess_fragment(SSL *s,struct hm_header_st *msg_hdr,int max)
+       {
+       size_t frag_off,frag_len,msg_len;
 
+       msg_len  = msg_hdr->msg_len;
+       frag_off = msg_hdr->frag_off;
+       frag_len = msg_hdr->frag_len;
 
-static int
-dtls1_buffer_handshake_fragment(SSL *s, struct hm_header_st* msg_hdr)
-{
-    hm_fragment *frag = NULL;
-    pitem *item = NULL;
-       PQ_64BIT seq64;
+       /* sanity checking */
+       if ( (frag_off+frag_len) > msg_len)
+               {
+               SSLerr(SSL_F_DTLS1_PREPROCESS_FRAGMENT,SSL_R_EXCESSIVE_MESSAGE_SIZE);
+               return SSL_AD_ILLEGAL_PARAMETER;
+               }
 
-    frag = dtls1_hm_fragment_new(msg_hdr->frag_len);
-    if ( frag == NULL)
-        goto err;
+       if ( (frag_off+frag_len) > (unsigned long)max)
+               {
+               SSLerr(SSL_F_DTLS1_PREPROCESS_FRAGMENT,SSL_R_EXCESSIVE_MESSAGE_SIZE);
+               return SSL_AD_ILLEGAL_PARAMETER;
+               }
 
-    memcpy(frag->fragment, &(s->init_buf->data[s->init_num]),
-        msg_hdr->frag_len + DTLS1_HM_HEADER_LENGTH);
+       if ( s->d1->r_msg_hdr.frag_off == 0) /* first fragment */
+               {
+               /* msg_len is limited to 2^24, but is effectively checked
+                * against max above */
+               if (!BUF_MEM_grow_clean(s->init_buf,(int)msg_len+DTLS1_HM_HEADER_LENGTH))
+                       {
+                       SSLerr(SSL_F_DTLS1_PREPROCESS_FRAGMENT,ERR_R_BUF_LIB);
+                       return SSL_AD_INTERNAL_ERROR;
+                       }
 
-    memcpy(&(frag->msg_header), msg_hdr, sizeof(*msg_hdr));
+               s->s3->tmp.message_size  = msg_len;
+               s->d1->r_msg_hdr.msg_len = msg_len;
+               s->s3->tmp.message_type  = msg_hdr->type;
+               s->d1->r_msg_hdr.type    = msg_hdr->type;
+               s->d1->r_msg_hdr.seq     = msg_hdr->seq;
+               }
+       else if (msg_len != s->d1->r_msg_hdr.msg_len)
+               {
+               /* They must be playing with us! BTW, failure to enforce
+                * upper limit would open possibility for buffer overrun. */
+               SSLerr(SSL_F_DTLS1_PREPROCESS_FRAGMENT,SSL_R_EXCESSIVE_MESSAGE_SIZE);
+               return SSL_AD_ILLEGAL_PARAMETER;
+               }
+
+       return 0; /* no error */
+       }
 
-    pq_64bit_init(&seq64);
-    pq_64bit_assign_word(&seq64, msg_hdr->seq);
 
-    item = pitem_new(seq64, frag);
-    if ( item == NULL)
-        goto err;
+static int
+dtls1_retrieve_buffered_fragment(SSL *s, long max, int *ok)
+       {
+       /* (0) check whether the desired fragment is available
+        * if so:
+        * (1) copy over the fragment to s->init_buf->data[]
+        * (2) update s->init_num
+        */
+       pitem *item;
+       hm_fragment *frag;
+       int al;
 
-    pq_64bit_free(&seq64);
+       *ok = 0;
+       item = pqueue_peek(s->d1->buffered_messages);
+       if ( item == NULL)
+               return 0;
 
-    pqueue_insert(s->d1->buffered_messages, item);
-    return 1;
+       frag = (hm_fragment *)item->data;
 
-err:
-    if ( frag != NULL) dtls1_hm_fragment_free(frag);
-    if ( item != NULL) OPENSSL_free(item);
-    return 0;
-}
+       if ( s->d1->handshake_read_seq == frag->msg_header.seq)
+               {
+               pqueue_pop(s->d1->buffered_messages);
 
+               al=dtls1_preprocess_fragment(s,&frag->msg_header,max);
 
-static void
-dtls1_process_handshake_fragment(SSL *s, int frag_len)
-    {
-    unsigned char *p;
+               if (al==0) /* no alert */
+                       {
+                       unsigned char *p = (unsigned char *)s->init_buf->data+DTLS1_HM_HEADER_LENGTH;
+                       memcpy(&p[frag->msg_header.frag_off],
+                               frag->fragment,frag->msg_header.frag_len);
+                       }
 
-    p = (unsigned char *)s->init_buf->data;
+               dtls1_hm_fragment_free(frag);
+               pitem_free(item);
 
-       ssl3_finish_mac(s, &p[s->init_num - frag_len], frag_len);
-    }
+               if (al==0)
+                       {
+                       *ok = 1;
+                       return frag->msg_header.frag_len;
+                       }
+
+               ssl3_send_alert(s,SSL3_AL_FATAL,al);
+               s->init_num = 0;
+               *ok = 0;
+               return -1;
+               }
+       else
+               return 0;
+       }
 
 
 static int
-dtls1_process_out_of_seq_message(SSL *s, struct hm_header_st *msg_hdr, int *ok)
-    {
-    int i;
-    unsigned char *p;
-
-    /* make sure there's enough room to read this fragment */
-    if ( (int)msg_hdr->frag_len && !BUF_MEM_grow_clean(s->init_buf, 
-             (int)msg_hdr->frag_len + DTLS1_HM_HEADER_LENGTH + s->init_num))
-        {
-        SSLerr(SSL_F_DTLS1_PROCESS_OUT_OF_SEQ_MESSAGE,ERR_R_BUF_LIB);
-        goto err;
-        }
-
-    p = (unsigned char *)s->init_buf->data;
-
-    /* read the body of the fragment (header has already been read */
-    if ( msg_hdr->frag_len > 0)
+dtls1_process_out_of_seq_message(SSL *s, struct hm_header_st* msg_hdr, int *ok)
+{
+       int i=-1;
+       hm_fragment *frag = NULL;
+       pitem *item = NULL;
+       PQ_64BIT seq64;
+       unsigned long frag_len = msg_hdr->frag_len;
+
+       if ((msg_hdr->frag_off+frag_len) > msg_hdr->msg_len)
+               goto err;
+
+       if (msg_hdr->seq <= s->d1->handshake_read_seq)
                {
-               i=s->method->ssl_read_bytes(s,SSL3_RT_HANDSHAKE,
-            &p[s->init_num], 
-            msg_hdr->frag_len,0);
-               if (i <= 0)
+               unsigned char devnull [256];
+
+               while (frag_len)
                        {
-                       *ok = 0;
-                       return i;
+                       i = s->method->ssl_read_bytes(s,SSL3_RT_HANDSHAKE,
+                               devnull,
+                               frag_len>sizeof(devnull)?sizeof(devnull):frag_len,0);
+                       if (i<=0) goto err;
+                       frag_len -= i;
                        }
                }
 
-    if ( msg_hdr->seq > s->d1->handshake_read_seq)
-        dtls1_buffer_handshake_fragment(s, msg_hdr);
-    else
-        OPENSSL_assert(msg_hdr->seq < s->d1->handshake_read_seq);
+       frag = dtls1_hm_fragment_new(frag_len);
+       if ( frag == NULL)
+               goto err;
+
+       memcpy(&(frag->msg_header), msg_hdr, sizeof(*msg_hdr));
+
+       if (frag_len)
+               {
+               /* read the body of the fragment (header has already been read */
+               i = s->method->ssl_read_bytes(s,SSL3_RT_HANDSHAKE,
+                       frag->fragment,frag_len,0);
+               if (i<=0 || (unsigned long)i!=frag_len)
+                       goto err;
+               }
+
+       pq_64bit_init(&seq64);
+       pq_64bit_assign_word(&seq64, msg_hdr->seq);
+
+       item = pitem_new(seq64, frag);
+       pq_64bit_free(&seq64);
+       if ( item == NULL)
+               goto err;
+
+       pqueue_insert(s->d1->buffered_messages, item);
+       return DTLS1_HM_FRAGMENT_RETRY;
 
-    return DTLS1_HM_FRAGMENT_RETRY;
 err:
-    *ok = 0;
-    return -1;
-    }
+       if ( frag != NULL) dtls1_hm_fragment_free(frag);
+       if ( item != NULL) OPENSSL_free(item);
+       *ok = 0;
+       return i;
+       }
 
 
 static long
 dtls1_get_message_fragment(SSL *s, int st1, int stn, long max, int *ok)
        {
-       unsigned char *p;
+       unsigned char wire[DTLS1_HM_HEADER_LENGTH];
        unsigned long l, frag_off, frag_len;
        int i,al;
        struct hm_header_st msg_hdr;
-    unsigned long overlap;
-    
-    /* see if we have the required fragment already */
-    if (dtls1_retrieve_buffered_fragment(s, &l))
-    {
-        /* compute MAC, remove fragment headers */
-        dtls1_process_handshake_fragment(s, l);
-        s->init_msg = s->init_buf->data + DTLS1_HM_HEADER_LENGTH;
-        s->state = stn;
-        return 1;
-    }
-
-    /* get a handshake fragment from the record layer */
-       p = (unsigned char *)s->init_buf->data;
-
-    /* read handshake message header */
-       i=s->method->ssl_read_bytes(s,SSL3_RT_HANDSHAKE,&p[s->init_num],
+
+       /* see if we have the required fragment already */
+       if ((frag_len = dtls1_retrieve_buffered_fragment(s,max,ok)) || *ok)
+               {
+               if (*ok)        s->init_num += frag_len;
+               return frag_len;
+               }
+
+       /* read handshake message header */
+       i=s->method->ssl_read_bytes(s,SSL3_RT_HANDSHAKE,wire,
                DTLS1_HM_HEADER_LENGTH, 0);
        if (i <= 0)     /* nbio, or an error */
                {
@@ -555,130 +633,61 @@ dtls1_get_message_fragment(SSL *s, int st1, int stn, long max, int *ok)
                *ok = 0;
                return i;
                }
-
        OPENSSL_assert(i == DTLS1_HM_HEADER_LENGTH);
 
-       p += s->init_num;
-    /* parse the message fragment header */
-    
-    dtls1_get_message_header(p, &msg_hdr);
+       /* parse the message fragment header */
+       dtls1_get_message_header(wire, &msg_hdr);
 
-    /* 
-     * if this is a future (or stale) message it gets buffered
-     * (or dropped)--no further processing at this time 
-     */
-    if ( msg_hdr.seq != s->d1->handshake_read_seq)
-        return dtls1_process_out_of_seq_message(s, &msg_hdr, ok);
+       /* 
+        * if this is a future (or stale) message it gets buffered
+        * (or dropped)--no further processing at this time 
+        */
+       if ( msg_hdr.seq != s->d1->handshake_read_seq)
+               return dtls1_process_out_of_seq_message(s, &msg_hdr, ok);
 
-    l = msg_hdr.msg_len;
-    frag_off = msg_hdr.frag_off;
+       l = msg_hdr.msg_len;
+       frag_off = msg_hdr.frag_off;
        frag_len = msg_hdr.frag_len;
 
-    /* sanity checking */
-    if ( frag_off + frag_len > l)
-        {
-        al=SSL_AD_ILLEGAL_PARAMETER;
-        SSLerr(SSL_F_DTLS1_GET_MESSAGE_FRAGMENT,SSL_R_EXCESSIVE_MESSAGE_SIZE);
-        goto f_err;
-        }
-
        if (!s->server && s->d1->r_msg_hdr.frag_off == 0 &&
-        p[0] == SSL3_MT_HELLO_REQUEST)
-        {
-        /* The server may always send 'Hello Request' messages --
-         * we are doing a handshake anyway now, so ignore them
-         * if their format is correct. Does not count for
-         * 'Finished' MAC. */
-        if (p[1] == 0 && p[2] == 0 &&p[3] == 0)
-            {
-            if (s->msg_callback)
-                s->msg_callback(0, s->version, SSL3_RT_HANDSHAKE, 
-                    p, DTLS1_HM_HEADER_LENGTH, s, 
-                    s->msg_callback_arg);
-            
-            s->init_num = 0;
-            return dtls1_get_message_fragment(s, st1, stn,
-                max, ok);
-            }
-        else /* Incorrectly formated Hello request */
-            {
-            al=SSL_AD_UNEXPECTED_MESSAGE;
-            SSLerr(SSL_F_DTLS1_GET_MESSAGE_FRAGMENT,SSL_R_UNEXPECTED_MESSAGE);
-            goto f_err;
-            }
-        }
-
-    /* XDTLS: do a sanity check on the fragment */
-
-    s->init_num += i;
-
-       if ( s->d1->r_msg_hdr.frag_off == 0) /* first fragment */
+               wire[0] == SSL3_MT_HELLO_REQUEST)
                {
-               /* BUF_MEM_grow takes an 'int' parameter */
-               if (l > (INT_MAX-DTLS1_HM_HEADER_LENGTH)) 
-                       {
-                       al=SSL_AD_ILLEGAL_PARAMETER;
-                       SSLerr(SSL_F_DTLS1_GET_MESSAGE_FRAGMENT,SSL_R_EXCESSIVE_MESSAGE_SIZE);
-                       goto f_err;
-                       }
-               if (l && !BUF_MEM_grow_clean(s->init_buf,(int)l
-                       + DTLS1_HM_HEADER_LENGTH))
+               /* The server may always send 'Hello Request' messages --
+                * we are doing a handshake anyway now, so ignore them
+                * if their format is correct. Does not count for
+                * 'Finished' MAC. */
+               if (wire[1] == 0 && wire[2] == 0 && wire[3] == 0)
                        {
-                       SSLerr(SSL_F_DTLS1_GET_MESSAGE_FRAGMENT,ERR_R_BUF_LIB);
-                       goto err;
+                       if (s->msg_callback)
+                               s->msg_callback(0, s->version, SSL3_RT_HANDSHAKE, 
+                                       wire, DTLS1_HM_HEADER_LENGTH, s, 
+                                       s->msg_callback_arg);
+                       
+                       s->init_num = 0;
+                       return dtls1_get_message_fragment(s, st1, stn,
+                               max, ok);
                        }
-        /* Only do this test when we're reading the expected message.
-         * Stale messages will be dropped and future messages will be buffered */
-        if ( l > (unsigned long)max)
+               else /* Incorrectly formated Hello request */
                        {
-                       al=SSL_AD_ILLEGAL_PARAMETER;
-                       SSLerr(SSL_F_DTLS1_GET_MESSAGE_FRAGMENT,SSL_R_EXCESSIVE_MESSAGE_SIZE);
+                       al=SSL_AD_UNEXPECTED_MESSAGE;
+                       SSLerr(SSL_F_DTLS1_GET_MESSAGE_FRAGMENT,SSL_R_UNEXPECTED_MESSAGE);
                        goto f_err;
                        }
-
-               s->s3->tmp.message_size=l;
                }
 
-    if ( frag_len > (unsigned long)max)
-        {
-        al=SSL_AD_ILLEGAL_PARAMETER;
-        SSLerr(SSL_F_DTLS1_GET_MESSAGE_FRAGMENT,SSL_R_EXCESSIVE_MESSAGE_SIZE);
-        goto f_err;
-        }
-    if ( frag_len + s->init_num > (INT_MAX - DTLS1_HM_HEADER_LENGTH))
-        {
-        al=SSL_AD_ILLEGAL_PARAMETER;
-        SSLerr(SSL_F_DTLS1_GET_MESSAGE_FRAGMENT,SSL_R_EXCESSIVE_MESSAGE_SIZE);
-        goto f_err;
-        }
-
-    if ( frag_len & !BUF_MEM_grow_clean(s->init_buf, (int)frag_len 
-             + DTLS1_HM_HEADER_LENGTH + s->init_num))
-        {
-        SSLerr(SSL_F_DTLS1_GET_MESSAGE_FRAGMENT,ERR_R_BUF_LIB);
-        goto err;
-        }
-
-       if ( s->d1->r_msg_hdr.frag_off == 0)
-               {
-               s->s3->tmp.message_type = msg_hdr.type;
-               s->d1->r_msg_hdr.type = msg_hdr.type;
-               s->d1->r_msg_hdr.msg_len = l;
-               /* s->d1->r_msg_hdr.seq = seq_num; */
-               }
+       if ((al=dtls1_preprocess_fragment(s,&msg_hdr,max)))
+               goto f_err;
 
        /* XDTLS:  ressurect this when restart is in place */
        s->state=stn;
-       
-       /* next state (stn) */
-       p = (unsigned char *)s->init_buf->data;
 
        if ( frag_len > 0)
                {
+               unsigned char *p=(unsigned char *)s->init_buf->data+DTLS1_HM_HEADER_LENGTH;
+
                i=s->method->ssl_read_bytes(s,SSL3_RT_HANDSHAKE,
-            &p[s->init_num], 
-            frag_len,0);
-        /* XDTLS:  fix this--message fragments cannot span multiple packets */
+                       &p[frag_off],frag_len,0);
+               /* XDTLS:  fix this--message fragments cannot span multiple packets */
                if (i <= 0)
                        {
                        s->rwstate=SSL_READING;
@@ -689,70 +698,23 @@ dtls1_get_message_fragment(SSL *s, int st1, int stn, long max, int *ok)
        else
                i = 0;
 
-    /* XDTLS:  an incorrectly formatted fragment should cause the 
-     * handshake to fail */
+       /* XDTLS:  an incorrectly formatted fragment should cause the 
+        * handshake to fail */
        OPENSSL_assert(i == (int)frag_len);
 
-#if 0
-    /* Successfully read a fragment.
-     * It may be (1) out of order, or
-     *           (2) it's a repeat, in which case we dump it
-     *           (3) the one we are expecting next (maybe with overlap)
-     * If it is next one, it may overlap with previously read bytes
-     */
-
-    /* case (1): buffer the future fragment 
-     * (we can treat fragments from a future message the same
-     * as future fragments from the message being currently read, since
-     * they are sematically simply out of order.
-     */
-    if ( msg_hdr.seq > s->d1->handshake_read_seq ||
-        frag_off > s->init_num - DTLS1_HM_HEADER_LENGTH)
-    {
-        dtls1_buffer_handshake_fragment(s, &msg_hdr);
-        return DTLS1_HM_FRAGMENT_RETRY;
-    }
-
-    /* case (2):  drop the entire fragment, and try again */
-    if ( msg_hdr.seq < s->d1->handshake_read_seq ||
-        frag_off + frag_len < s->init_num - DTLS1_HM_HEADER_LENGTH)
-        {
-        s->init_num -= DTLS1_HM_HEADER_LENGTH;
-        return DTLS1_HM_FRAGMENT_RETRY;
-        }
-#endif
+       *ok = 1;
 
-    /* case (3): received a immediately useful fragment.  Determine the 
-     * possible overlap and copy the fragment.
-     */
-    overlap = (s->init_num - DTLS1_HM_HEADER_LENGTH) - frag_off;
-        
-    /* retain the header for the first fragment */
-    if ( s->init_num > DTLS1_HM_HEADER_LENGTH)
-        {
-        memmove(&(s->init_buf->data[s->init_num]),
-            &(s->init_buf->data[s->init_num + DTLS1_HM_HEADER_LENGTH + overlap]),
-            frag_len - overlap);
-
-        s->init_num += frag_len - overlap;
-        }
-    else
-        s->init_num += frag_len;
-
-    dtls1_process_handshake_fragment(s, frag_len - overlap);
-
-       if (s->msg_callback)
-               s->msg_callback(0, s->version, SSL3_RT_HANDSHAKE, s->init_buf->data, 
-                       (size_t)s->init_num, s, 
-                       s->msg_callback_arg);
-       *ok=1;
-
-       return s->init_num;
+       /* Note that s->init_num is *not* used as current offset in
+        * s->init_buf->data, but as a counter summing up fragments'
+        * lengths: as soon as they sum up to handshake packet
+        * length, we assume we have got all the fragments. */
+       s->init_num += frag_len;
+       return frag_len;
 
 f_err:
        ssl3_send_alert(s,SSL3_AL_FATAL,al);
-    s->init_num = 0;
-err:
+       s->init_num = 0;
+
        *ok=0;
        return(-1);
        }
@@ -790,7 +752,7 @@ int dtls1_send_finished(SSL *s, int a, int b, const char *sender, int slen)
 
                /* buffer the message to handle re-xmits */
                dtls1_buffer_message(s, 0);
-               
+
                s->state=b;
                }
 
@@ -815,10 +777,15 @@ int dtls1_send_change_cipher_spec(SSL *s, int a, int b)
                p=(unsigned char *)s->init_buf->data;
                *p++=SSL3_MT_CCS;
                s->d1->handshake_write_seq = s->d1->next_handshake_write_seq;
-               s->d1->next_handshake_write_seq++;
-               s2n(s->d1->handshake_write_seq,p);
-
                s->init_num=DTLS1_CCS_HEADER_LENGTH;
+
+               if (s->client_version == DTLS1_BAD_VER)
+                       {
+                       s->d1->next_handshake_write_seq++;
+                       s2n(s->d1->handshake_write_seq,p);
+                       s->init_num+=2;
+                       }
+
                s->init_off=0;
 
                dtls1_set_message_header_int(s, SSL3_MT_CCS, 0, 
@@ -915,316 +882,280 @@ unsigned long dtls1_output_cert_chain(SSL *s, X509 *x)
        }
 
 int dtls1_read_failed(SSL *s, int code)
-    {
-    DTLS1_STATE *state;
-    BIO *bio;
-    int send_alert = 0;
-
-    if ( code > 0)
-        {
-        fprintf( stderr, "invalid state reached %s:%d", __FILE__, __LINE__);
-        return 1;
-        }
-
-    bio = SSL_get_rbio(s);
-    if ( ! BIO_dgram_recv_timedout(bio))
-        {
-        /* not a timeout, none of our business, 
-           let higher layers handle this.  in fact it's probably an error */
-        return code;
-        }
-
-    if ( ! SSL_in_init(s))  /* done, no need to send a retransmit */
-        {
-        BIO_set_flags(SSL_get_rbio(s), BIO_FLAGS_READ);
-        return code;
-        }
-
-    state = s->d1;
-    state->timeout.num_alerts++;
-    if ( state->timeout.num_alerts > DTLS1_TMO_ALERT_COUNT)
-        {
-        /* fail the connection, enough alerts have been sent */
-        SSLerr(SSL_F_DTLS1_READ_FAILED,SSL_R_READ_TIMEOUT_EXPIRED);
-        return 0;
-        }
-       
-    state->timeout.read_timeouts++;
-    if ( state->timeout.read_timeouts > DTLS1_TMO_READ_COUNT)
-        {
-        send_alert = 1;
-        state->timeout.read_timeouts = 1;
-        }
-
-       
+       {
+       DTLS1_STATE *state;
+       BIO *bio;
+       int send_alert = 0;
+
+       if ( code > 0)
+               {
+               fprintf( stderr, "invalid state reached %s:%d", __FILE__, __LINE__);
+               return 1;
+               }
+
+       bio = SSL_get_rbio(s);
+       if ( ! BIO_dgram_recv_timedout(bio))
+               {
+               /* not a timeout, none of our business, 
+                  let higher layers handle this.  in fact it's probably an error */
+               return code;
+               }
+
+       if ( ! SSL_in_init(s))  /* done, no need to send a retransmit */
+               {
+               BIO_set_flags(SSL_get_rbio(s), BIO_FLAGS_READ);
+               return code;
+               }
+
+       state = s->d1;
+       state->timeout.num_alerts++;
+       if ( state->timeout.num_alerts > DTLS1_TMO_ALERT_COUNT)
+               {
+               /* fail the connection, enough alerts have been sent */
+               SSLerr(SSL_F_DTLS1_READ_FAILED,SSL_R_READ_TIMEOUT_EXPIRED);
+               return 0;
+               }
+
+       state->timeout.read_timeouts++;
+       if ( state->timeout.read_timeouts > DTLS1_TMO_READ_COUNT)
+               {
+               send_alert = 1;
+               state->timeout.read_timeouts = 1;
+               }
+
+
 #if 0 /* for now, each alert contains only one record number */
-    item = pqueue_peek(state->rcvd_records);
-    if ( item )
-        {
-        /* send an alert immediately for all the missing records */
-        }
-    else
+       item = pqueue_peek(state->rcvd_records);
+       if ( item )
+               {
+               /* send an alert immediately for all the missing records */
+               }
+       else
 #endif
 
 #if 0  /* no more alert sending, just retransmit the last set of messages */
-        if ( send_alert)
-            ssl3_send_alert(s,SSL3_AL_WARNING,
-                DTLS1_AD_MISSING_HANDSHAKE_MESSAGE);
+               if ( send_alert)
+                       ssl3_send_alert(s,SSL3_AL_WARNING,
+                               DTLS1_AD_MISSING_HANDSHAKE_MESSAGE);
 #endif
 
-    return dtls1_retransmit_buffered_messages(s) ;
-    }
+       return dtls1_retransmit_buffered_messages(s) ;
+       }
 
 
 static int
 dtls1_retransmit_buffered_messages(SSL *s)
-    {
-    pqueue sent = s->d1->sent_messages;
-    piterator iter;
-    pitem *item;
-    hm_fragment *frag;
-    int found = 0;
-
-    iter = pqueue_iterator(sent);
-
-    for ( item = pqueue_next(&iter); item != NULL; item = pqueue_next(&iter))
-        {
-        frag = (hm_fragment *)item->data;
-        if ( dtls1_retransmit_message(s, frag->msg_header.seq, 0, &found) <= 0 &&
-            found)
-            {
-            fprintf(stderr, "dtls1_retransmit_message() failed\n");
-            return -1;
-            }
-        }
-
-    return 1;
-    }
+       {
+       pqueue sent = s->d1->sent_messages;
+       piterator iter;
+       pitem *item;
+       hm_fragment *frag;
+       int found = 0;
 
-#if 0
-static dtls1_message_buffer *
-dtls1_message_buffer_new(unsigned int len)
-    {
-    dtls1_message_buffer *msg_buf;
-
-    msg_buf = (dtls1_message_buffer *) 
-        OPENSSL_malloc(sizeof(dtls1_message_buffer)); 
-    if ( msg_buf == NULL)
-        return NULL;
-
-    memset(msg_buf, 0x00, sizeof(dtls1_message_buffer));
-
-    msg_buf->data = (unsigned char *) OPENSSL_malloc(len);
-    if ( msg_buf->data == NULL)
-        {
-        OPENSSL_free(msg_buf);
-        return NULL;
-        }
-
-    memset(msg_buf->data, 0x00, len);
-    return msg_buf;
-    }
-#endif
+       iter = pqueue_iterator(sent);
 
-#if 0
-static void
-dtls1_message_buffer_free(dtls1_message_buffer *msg_buf)
-    {
-    if (msg_buf != NULL)
-        {
-        OPENSSL_free(msg_buf->data);
-        OPENSSL_free(msg_buf);
-        }
-    }
-#endif
+       for ( item = pqueue_next(&iter); item != NULL; item = pqueue_next(&iter))
+               {
+               frag = (hm_fragment *)item->data;
+               if ( dtls1_retransmit_message(s, frag->msg_header.seq, 0, &found) <= 0 &&
+                       found)
+                       {
+                       fprintf(stderr, "dtls1_retransmit_message() failed\n");
+                       return -1;
+                       }
+               }
+
+       return 1;
+       }
 
 int
 dtls1_buffer_message(SSL *s, int is_ccs)
-    {
-    pitem *item;
-    hm_fragment *frag;
+       {
+       pitem *item;
+       hm_fragment *frag;
        PQ_64BIT seq64;
+       unsigned int epoch = s->d1->w_epoch;
+
+       /* this function is called immediately after a message has 
+        * been serialized */
+       OPENSSL_assert(s->init_off == 0);
+
+       frag = dtls1_hm_fragment_new(s->init_num);
+
+       memcpy(frag->fragment, s->init_buf->data, s->init_num);
+
+       if ( is_ccs)
+               {
+               OPENSSL_assert(s->d1->w_msg_hdr.msg_len + 
+                       DTLS1_CCS_HEADER_LENGTH <= (unsigned int)s->init_num);
+               epoch++;
+               }
+       else
+               {
+               OPENSSL_assert(s->d1->w_msg_hdr.msg_len + 
+                       DTLS1_HM_HEADER_LENGTH == (unsigned int)s->init_num);
+               }
+
+       frag->msg_header.msg_len = s->d1->w_msg_hdr.msg_len;
+       frag->msg_header.seq = s->d1->w_msg_hdr.seq;
+       frag->msg_header.type = s->d1->w_msg_hdr.type;
+       frag->msg_header.frag_off = 0;
+       frag->msg_header.frag_len = s->d1->w_msg_hdr.msg_len;
+       frag->msg_header.is_ccs = is_ccs;
 
-    /* this function is called immediately after a message has 
-     * been serialized */
-    OPENSSL_assert(s->init_off == 0);
-
-    frag = dtls1_hm_fragment_new(s->init_num);
-
-    memcpy(frag->fragment, s->init_buf->data, s->init_num);
-
-    if ( is_ccs)
-        {
-        OPENSSL_assert(s->d1->w_msg_hdr.msg_len + 
-            DTLS1_CCS_HEADER_LENGTH == (unsigned int)s->init_num);
-        }
-    else
-        {
-        OPENSSL_assert(s->d1->w_msg_hdr.msg_len + 
-            DTLS1_HM_HEADER_LENGTH == (unsigned int)s->init_num);
-        }
-
-    frag->msg_header.msg_len = s->d1->w_msg_hdr.msg_len;
-    frag->msg_header.seq = s->d1->w_msg_hdr.seq;
-    frag->msg_header.type = s->d1->w_msg_hdr.type;
-    frag->msg_header.frag_off = 0;
-    frag->msg_header.frag_len = s->d1->w_msg_hdr.msg_len;
-    frag->msg_header.is_ccs = is_ccs;
-
-    pq_64bit_init(&seq64);
-    pq_64bit_assign_word(&seq64, frag->msg_header.seq);
-
-    item = pitem_new(seq64, frag);
-    pq_64bit_free(&seq64);
-    if ( item == NULL)
-        {
-        dtls1_hm_fragment_free(frag);
-        return 0;
-        }
+       pq_64bit_init(&seq64);
+       pq_64bit_assign_word(&seq64, epoch<<16 | frag->msg_header.seq);
+
+       item = pitem_new(seq64, frag);
+       pq_64bit_free(&seq64);
+       if ( item == NULL)
+               {
+               dtls1_hm_fragment_free(frag);
+               return 0;
+               }
 
 #if 0
-    fprintf( stderr, "buffered messge: \ttype = %xx\n", msg_buf->type);
-    fprintf( stderr, "\t\t\t\t\tlen = %d\n", msg_buf->len);
-    fprintf( stderr, "\t\t\t\t\tseq_num = %d\n", msg_buf->seq_num);
+       fprintf( stderr, "buffered messge: \ttype = %xx\n", msg_buf->type);
+       fprintf( stderr, "\t\t\t\t\tlen = %d\n", msg_buf->len);
+       fprintf( stderr, "\t\t\t\t\tseq_num = %d\n", msg_buf->seq_num);
 #endif
 
-    pqueue_insert(s->d1->sent_messages, item);
-    return 1;
-    }
+       pqueue_insert(s->d1->sent_messages, item);
+       return 1;
+       }
 
 int
 dtls1_retransmit_message(SSL *s, unsigned short seq, unsigned long frag_off,
-    int *found)
-    {
-    int ret;
-    /* XDTLS: for now assuming that read/writes are blocking */
-    pitem *item;
-    hm_fragment *frag ;
-    unsigned long header_length;
+       int *found)
+       {
+       int ret;
+       /* XDTLS: for now assuming that read/writes are blocking */
+       pitem *item;
+       hm_fragment *frag ;
+       unsigned long header_length;
        PQ_64BIT seq64;
 
-    /*
-      OPENSSL_assert(s->init_num == 0);
-      OPENSSL_assert(s->init_off == 0);
-     */
-
-    /* XDTLS:  the requested message ought to be found, otherwise error */
-    pq_64bit_init(&seq64);
-    pq_64bit_assign_word(&seq64, seq);
-
-    item = pqueue_find(s->d1->sent_messages, seq64);
-    pq_64bit_free(&seq64);
-    if ( item == NULL)
-        {
-        fprintf(stderr, "retransmit:  message %d non-existant\n", seq);
-        *found = 0;
-        return 0;
-        }
-
-    *found = 1;
-    frag = (hm_fragment *)item->data;
-
-    if ( frag->msg_header.is_ccs)
-        header_length = DTLS1_CCS_HEADER_LENGTH;
-    else
-        header_length = DTLS1_HM_HEADER_LENGTH;
-
-    memcpy(s->init_buf->data, frag->fragment, 
-        frag->msg_header.msg_len + header_length);
-        s->init_num = frag->msg_header.msg_len + header_length;
-    
-    dtls1_set_message_header_int(s, frag->msg_header.type, 
-        frag->msg_header.msg_len, frag->msg_header.seq, 0, 
-        frag->msg_header.frag_len);
-
-    s->d1->retransmitting = 1;
-    ret = dtls1_do_write(s, frag->msg_header.is_ccs ? 
-        SSL3_RT_CHANGE_CIPHER_SPEC : SSL3_RT_HANDSHAKE);
-    s->d1->retransmitting = 0;
-
-    (void)BIO_flush(SSL_get_wbio(s));
-    return ret;
-    }
+       /*
+         OPENSSL_assert(s->init_num == 0);
+         OPENSSL_assert(s->init_off == 0);
+        */
+
+       /* XDTLS:  the requested message ought to be found, otherwise error */
+       pq_64bit_init(&seq64);
+       pq_64bit_assign_word(&seq64, seq);
+
+       item = pqueue_find(s->d1->sent_messages, seq64);
+       pq_64bit_free(&seq64);
+       if ( item == NULL)
+               {
+               fprintf(stderr, "retransmit:  message %d non-existant\n", seq);
+               *found = 0;
+               return 0;
+               }
+
+       *found = 1;
+       frag = (hm_fragment *)item->data;
+
+       if ( frag->msg_header.is_ccs)
+               header_length = DTLS1_CCS_HEADER_LENGTH;
+       else
+               header_length = DTLS1_HM_HEADER_LENGTH;
+
+       memcpy(s->init_buf->data, frag->fragment, 
+               frag->msg_header.msg_len + header_length);
+               s->init_num = frag->msg_header.msg_len + header_length;
+
+       dtls1_set_message_header_int(s, frag->msg_header.type, 
+               frag->msg_header.msg_len, frag->msg_header.seq, 0, 
+               frag->msg_header.frag_len);
+
+       s->d1->retransmitting = 1;
+       ret = dtls1_do_write(s, frag->msg_header.is_ccs ? 
+               SSL3_RT_CHANGE_CIPHER_SPEC : SSL3_RT_HANDSHAKE);
+       s->d1->retransmitting = 0;
+
+       (void)BIO_flush(SSL_get_wbio(s));
+       return ret;
+       }
 
 /* call this function when the buffered messages are no longer needed */
 void
 dtls1_clear_record_buffer(SSL *s)
-    {
-    pitem *item;
-    
-    for(item = pqueue_pop(s->d1->sent_messages);
-        item != NULL; item = pqueue_pop(s->d1->sent_messages))
-        {
-        dtls1_hm_fragment_free((hm_fragment *)item->data);
-        pitem_free(item);
-        }
-    }
+       {
+       pitem *item;
+
+       for(item = pqueue_pop(s->d1->sent_messages);
+               item != NULL; item = pqueue_pop(s->d1->sent_messages))
+               {
+               dtls1_hm_fragment_free((hm_fragment *)item->data);
+               pitem_free(item);
+               }
+       }
 
 
 unsigned char *
 dtls1_set_message_header(SSL *s, unsigned char *p, unsigned char mt,
-    unsigned long len, unsigned long frag_off, unsigned long frag_len)
-    {
-    if ( frag_off == 0)
-        {
-        s->d1->handshake_write_seq = s->d1->next_handshake_write_seq;
-        s->d1->next_handshake_write_seq++;
-        }
-    
-    dtls1_set_message_header_int(s, mt, len, s->d1->handshake_write_seq,
-        frag_off, frag_len);
-    
-    return p += DTLS1_HM_HEADER_LENGTH;
-    }
+                       unsigned long len, unsigned long frag_off, unsigned long frag_len)
+       {
+       if ( frag_off == 0)
+               {
+               s->d1->handshake_write_seq = s->d1->next_handshake_write_seq;
+               s->d1->next_handshake_write_seq++;
+               }
+
+       dtls1_set_message_header_int(s, mt, len, s->d1->handshake_write_seq,
+               frag_off, frag_len);
+
+       return p += DTLS1_HM_HEADER_LENGTH;
+       }
 
 
 /* don't actually do the writing, wait till the MTU has been retrieved */
 static void
 dtls1_set_message_header_int(SSL *s, unsigned char mt,
-    unsigned long len, unsigned short seq_num, unsigned long frag_off, 
-    unsigned long frag_len)
-    {
-    struct hm_header_st *msg_hdr = &s->d1->w_msg_hdr;
-    
-    msg_hdr->type = mt;
-    msg_hdr->msg_len = len;
-    msg_hdr->seq = seq_num;
-    msg_hdr->frag_off = frag_off;
-    msg_hdr->frag_len = frag_len;
-}
+                           unsigned long len, unsigned short seq_num, unsigned long frag_off,
+                           unsigned long frag_len)
+       {
+       struct hm_header_st *msg_hdr = &s->d1->w_msg_hdr;
+
+       msg_hdr->type = mt;
+       msg_hdr->msg_len = len;
+       msg_hdr->seq = seq_num;
+       msg_hdr->frag_off = frag_off;
+       msg_hdr->frag_len = frag_len;
+       }
 
 static void
 dtls1_fix_message_header(SSL *s, unsigned long frag_off,
-       unsigned long frag_len)
-    {
-    struct hm_header_st *msg_hdr = &s->d1->w_msg_hdr;
-    
-    msg_hdr->frag_off = frag_off;
-    msg_hdr->frag_len = frag_len;
-    }
+                       unsigned long frag_len)
+       {
+       struct hm_header_st *msg_hdr = &s->d1->w_msg_hdr;
+
+       msg_hdr->frag_off = frag_off;
+       msg_hdr->frag_len = frag_len;
+       }
 
 static unsigned char *
 dtls1_write_message_header(SSL *s, unsigned char *p)
-    {
-    struct hm_header_st *msg_hdr = &s->d1->w_msg_hdr;
-    
-    *p++ = msg_hdr->type;
-    l2n3(msg_hdr->msg_len, p);
-    
-    s2n(msg_hdr->seq, p);
-    l2n3(msg_hdr->frag_off, p);
-    l2n3(msg_hdr->frag_len, p);
-    
-    return p;
-    }
+       {
+       struct hm_header_st *msg_hdr = &s->d1->w_msg_hdr;
+
+       *p++ = msg_hdr->type;
+       l2n3(msg_hdr->msg_len, p);
+
+       s2n(msg_hdr->seq, p);
+       l2n3(msg_hdr->frag_off, p);
+       l2n3(msg_hdr->frag_len, p);
+
+       return p;
+       }
 
 static unsigned int 
 dtls1_min_mtu(void)
-    {
-    return 
-        g_probable_mtu[(sizeof(g_probable_mtu) / 
-           sizeof(g_probable_mtu[0])) - 1];
-    }
+       {
+       return (g_probable_mtu[(sizeof(g_probable_mtu) / 
+               sizeof(g_probable_mtu[0])) - 1]);
+       }
 
 static unsigned int 
 dtls1_guess_mtu(unsigned int curr_mtu)
@@ -1237,27 +1168,26 @@ dtls1_guess_mtu(unsigned int curr_mtu)
        for ( i = 0; i < sizeof(g_probable_mtu)/sizeof(g_probable_mtu[0]); i++)
                if ( curr_mtu > g_probable_mtu[i])
                        return g_probable_mtu[i];
-       
+
        return curr_mtu;
        }
 
 void
 dtls1_get_message_header(unsigned char *data, struct hm_header_st *msg_hdr)
-    {
-    memset(msg_hdr, 0x00, sizeof(struct hm_header_st));
-    msg_hdr->type = *(data++);
-    n2l3(data, msg_hdr->msg_len);
-    
-    n2s(data, msg_hdr->seq);
-    n2l3(data, msg_hdr->frag_off);
-    n2l3(data, msg_hdr->frag_len);
-    }
+       {
+       memset(msg_hdr, 0x00, sizeof(struct hm_header_st));
+       msg_hdr->type = *(data++);
+       n2l3(data, msg_hdr->msg_len);
+
+       n2s(data, msg_hdr->seq);
+       n2l3(data, msg_hdr->frag_off);
+       n2l3(data, msg_hdr->frag_len);
+       }
 
 void
 dtls1_get_ccs_header(unsigned char *data, struct ccs_header_st *ccs_hdr)
-    {
-    memset(ccs_hdr, 0x00, sizeof(struct ccs_header_st));
-    
-    ccs_hdr->type = *(data++);
-    n2s(data, ccs_hdr->seq);
-}
+       {
+       memset(ccs_hdr, 0x00, sizeof(struct ccs_header_st));
+
+       ccs_hdr->type = *(data++);
+       }
index e8b60a45d225a6a215d7fe99487866a3ebac7b38..5e59dc845ac0d50ef578e4b8338d7960dc989690 100644 (file)
@@ -214,17 +214,21 @@ int dtls1_connect(SSL *s)
 
                        /* don't push the buffering BIO quite yet */
 
-                       ssl3_init_finished_mac(s);
-
                        s->state=SSL3_ST_CW_CLNT_HELLO_A;
                        s->ctx->stats.sess_connect++;
                        s->init_num=0;
+                       /* mark client_random uninitialized */
+                       memset(s->s3->client_random,0,sizeof(s->s3->client_random));
                        break;
 
                case SSL3_ST_CW_CLNT_HELLO_A:
                case SSL3_ST_CW_CLNT_HELLO_B:
 
                        s->shutdown=0;
+
+                       /* every DTLS ClientHello resets Finished MAC */
+                       ssl3_init_finished_mac(s);
+
                        ret=dtls1_client_hello(s);
                        if (ret <= 0) goto end;
 
@@ -422,6 +426,9 @@ int dtls1_connect(SSL *s)
                                s->s3->tmp.next_state=SSL3_ST_CR_FINISHED_A;
                                }
                        s->init_num=0;
+                       /* mark client_random uninitialized */
+                       memset (s->s3->client_random,0,sizeof(s->s3->client_random));
+
                        break;
 
                case SSL3_ST_CR_FINISHED_A:
@@ -544,9 +551,15 @@ int dtls1_client_hello(SSL *s)
                /* else use the pre-loaded session */
 
                p=s->s3->client_random;
-               Time=(unsigned long)time(NULL);                 /* Time */
-               l2n(Time,p);
-               RAND_pseudo_bytes(p,SSL3_RANDOM_SIZE-sizeof(Time));
+               /* if client_random is initialized, reuse it, we are
+                * required to use same upon reply to HelloVerify */
+               for (i=0;p[i]=='\0' && i<sizeof(s->s3->client_random);i++) ;
+               if (i==sizeof(s->s3->client_random))
+                       {
+                       Time=(unsigned long)time(NULL); /* Time */
+                       l2n(Time,p);
+                       RAND_pseudo_bytes(p,SSL3_RANDOM_SIZE-4);
+                       }
 
                /* Do the message type and length last */
                d=p= &(buf[DTLS1_HM_HEADER_LENGTH]);
@@ -732,7 +745,7 @@ int dtls1_send_client_key_exchange(SSL *s)
                        s->session->master_key_length=sizeof tmp_buf;
 
                        q=p;
-                       /* Fix buf for TLS and beyond */
+                       /* Fix buf for TLS and [incidentally] DTLS */
                        if (s->version > SSL3_VERSION)
                                p+=2;
                        n=RSA_public_encrypt(sizeof tmp_buf,
@@ -747,7 +760,7 @@ int dtls1_send_client_key_exchange(SSL *s)
                                goto err;
                                }
 
-                       /* Fix buf for TLS and beyond */
+                       /* Fix buf for TLS and [incidentally] DTLS */
                        if (s->version > SSL3_VERSION)
                                {
                                s2n(n,q);
index d07a212faceabd612b335bb93e38a5cfd0940271..fc088b41489384927847e64d598d1e99b2099234 100644 (file)
@@ -188,3 +188,23 @@ void dtls1_clear(SSL *s)
        ssl3_clear(s);
        s->version=DTLS1_VERSION;
        }
+
+/*
+ * As it's impossible to use stream ciphers in "datagram" mode, this
+ * simple filter is designed to disengage them in DTLS. Unfortunately
+ * there is no universal way to identify stream SSL_CIPHER, so we have
+ * to explicitly list their SSL_* codes. Currently RC4 is the only one
+ * available, but if new ones emerge, they will have to be added...
+ */
+SSL_CIPHER *dtls1_get_cipher(unsigned int u)
+       {
+       SSL_CIPHER *ciph = ssl3_get_cipher(u);
+
+       if (ciph != NULL)
+               {
+               if ((ciph->algorithms&SSL_ENC_MASK) == SSL_RC4)
+                       return NULL;
+               }
+
+       return ciph;
+       }
index 8270419a8dceac6b69db4cf54733305d885c29b8..377696deac0bd2706464fe7a807169a9c5cfd399 100644 (file)
 #include <openssl/evp.h>
 #include <openssl/buffer.h>
 #include <openssl/pqueue.h>
+#include <openssl/rand.h>
 
 static int have_handshake_fragment(SSL *s, int type, unsigned char *buf, 
        int len, int peek);
@@ -486,9 +487,9 @@ int dtls1_get_record(SSL *s)
        SSL3_RECORD *rr;
        SSL_SESSION *sess;
        unsigned char *p;
-       short version;
+       unsigned short version;
        DTLS1_BITMAP *bitmap;
-    unsigned int is_next_epoch;
+       unsigned int is_next_epoch;
 
        rr= &(s->s3->rrec);
        sess=s->session;
@@ -524,7 +525,7 @@ again:
                ssl_minor= *(p++);
                version=(ssl_major<<8)|ssl_minor;
 
-        /* sequence number is 64 bits, with top 2 bytes = epoch */ 
+               /* sequence number is 64 bits, with top 2 bytes = epoch */ 
                n2s(p,rr->epoch);
 
                memcpy(&(s->s3->read_sequence[2]), p, 6);
@@ -535,7 +536,7 @@ again:
                /* Lets check version */
                if (!s->first_packet)
                        {
-                       if (version != s->version)
+                       if (version != s->version && version != DTLS1_BAD_VER)
                                {
                                SSLerr(SSL_F_DTLS1_GET_RECORD,SSL_R_WRONG_VERSION_NUMBER);
                                /* Send back error using their
@@ -546,7 +547,8 @@ again:
                                }
                        }
 
-               if ((version & 0xff00) != (DTLS1_VERSION & 0xff00))
+               if ((version & 0xff00) != (DTLS1_VERSION & 0xff00) &&
+                   (version & 0xff00) != (DTLS1_BAD_VER & 0xff00))
                        {
                        SSLerr(SSL_F_DTLS1_GET_RECORD,SSL_R_WRONG_VERSION_NUMBER);
                        goto err;
@@ -559,6 +561,7 @@ again:
                        goto f_err;
                        }
 
+               s->client_version = version;
                /* now s->rstate == SSL_ST_READ_BODY */
                }
 
@@ -973,47 +976,40 @@ start:
                }
 
        if (rr->type == SSL3_RT_CHANGE_CIPHER_SPEC)
-        {
-        struct ccs_header_st ccs_hdr;
+               {
+               struct ccs_header_st ccs_hdr;
 
                dtls1_get_ccs_header(rr->data, &ccs_hdr);
 
-               if ( ccs_hdr.seq == s->d1->handshake_read_seq)
+               /* 'Change Cipher Spec' is just a single byte, so we know
+                * exactly what the record payload has to look like */
+               /* XDTLS: check that epoch is consistent */
+               if (    (s->client_version == DTLS1_BAD_VER && rr->length != 3) ||
+                       (s->client_version != DTLS1_BAD_VER && rr->length != DTLS1_CCS_HEADER_LENGTH) || 
+                       (rr->off != 0) || (rr->data[0] != SSL3_MT_CCS))
                        {
-                       /* 'Change Cipher Spec' is just a single byte, so we know
-                        * exactly what the record payload has to look like */
-                       /* XDTLS: check that epoch is consistent */
-                       if (    (rr->length != DTLS1_CCS_HEADER_LENGTH) || 
-                               (rr->off != 0) || (rr->data[0] != SSL3_MT_CCS))
-                               {
-                               i=SSL_AD_ILLEGAL_PARAMETER;
-                               SSLerr(SSL_F_DTLS1_READ_BYTES,SSL_R_BAD_CHANGE_CIPHER_SPEC);
-                               goto err;
-                               }
-                       
-                       rr->length=0;
-                       
-                       if (s->msg_callback)
-                               s->msg_callback(0, s->version, SSL3_RT_CHANGE_CIPHER_SPEC, 
-                                       rr->data, 1, s, s->msg_callback_arg);
-                       
-                       s->s3->change_cipher_spec=1;
-                       if (!ssl3_do_change_cipher_spec(s))
-                               goto err;
-                       
-                       /* do this whenever CCS is processed */
-                       dtls1_reset_seq_numbers(s, SSL3_CC_READ);
-                       
-                       /* handshake read seq is reset upon handshake completion */
-                       s->d1->handshake_read_seq++;
-                       
-                       goto start;
-                       }
-               else
-                       {
-                       rr->length = 0;
-                       goto start;
+                       i=SSL_AD_ILLEGAL_PARAMETER;
+                       SSLerr(SSL_F_DTLS1_READ_BYTES,SSL_R_BAD_CHANGE_CIPHER_SPEC);
+                       goto err;
                        }
+
+               rr->length=0;
+
+               if (s->msg_callback)
+                       s->msg_callback(0, s->version, SSL3_RT_CHANGE_CIPHER_SPEC, 
+                               rr->data, 1, s, s->msg_callback_arg);
+
+               s->s3->change_cipher_spec=1;
+               if (!ssl3_do_change_cipher_spec(s))
+                       goto err;
+
+               /* do this whenever CCS is processed */
+               dtls1_reset_seq_numbers(s, SSL3_CC_READ);
+
+               if (s->client_version == DTLS1_BAD_VER)
+                       s->d1->handshake_read_seq++;
+
+               goto start;
                }
 
        /* Unexpected handshake message (Client Hello, or protocol violation) */
@@ -1341,8 +1337,12 @@ int do_dtls1_write(SSL *s, int type, const unsigned char *buf, unsigned int len,
        *(p++)=type&0xff;
        wr->type=type;
 
-       *(p++)=(s->version>>8);
-       *(p++)=s->version&0xff;
+       if (s->client_version == DTLS1_BAD_VER)
+               *(p++) = DTLS1_BAD_VER>>8,
+               *(p++) = DTLS1_BAD_VER&0xff;
+       else
+               *(p++)=(s->version>>8),
+               *(p++)=s->version&0xff;
 
        /* field where we are to write out packet epoch, seq num and len */
        pseq=p; 
@@ -1397,8 +1397,14 @@ int do_dtls1_write(SSL *s, int type, const unsigned char *buf, unsigned int len,
 
 
        /* ssl3_enc can only have an error on read */
-       wr->length += bs;  /* bs != 0 in case of CBC.  The enc fn provides
-                                               * the randomness */ 
+       if (bs) /* bs != 0 in case of CBC */
+               {
+               RAND_pseudo_bytes(p,bs);
+               /* master IV and last CBC residue stand for
+                * the rest of randomness */
+               wr->length += bs;
+               }
+
        s->method->ssl3_enc->enc(s,1);
 
        /* record length after mac and block padding */
index ff27b4b4674704c475b4720d3c6ee506ae4aa04f..927b01f3c477739fdab61cacea72b3f8ebb090c2 100644 (file)
@@ -285,6 +285,10 @@ int dtls1_accept(SSL *s)
                        s->d1->send_cookie = 0;
                        s->state=SSL3_ST_SW_FLUSH;
                        s->s3->tmp.next_state=SSL3_ST_SR_CLNT_HELLO_A;
+
+                       /* HelloVerifyRequests resets Finished MAC */
+                       if (s->client_version != DTLS1_BAD_VER)
+                               ssl3_init_finished_mac(s);
                        break;
                        
                case SSL3_ST_SW_SRVR_HELLO_A:
@@ -620,20 +624,24 @@ int dtls1_send_hello_verify_request(SSL *s)
                buf = (unsigned char *)s->init_buf->data;
 
                msg = p = &(buf[DTLS1_HM_HEADER_LENGTH]);
-               *(p++) = s->version >> 8;
-               *(p++) = s->version & 0xFF;
+               if (s->client_version == DTLS1_BAD_VER)
+                       *(p++) = DTLS1_BAD_VER>>8,
+                       *(p++) = DTLS1_BAD_VER&0xff;
+               else
+                       *(p++) = s->version >> 8,
+                       *(p++) = s->version & 0xFF;
 
-               *(p++) = (unsigned char) s->d1->cookie_len;
-        if ( s->ctx->app_gen_cookie_cb != NULL &&
-            s->ctx->app_gen_cookie_cb(s, s->d1->cookie, 
-                &(s->d1->cookie_len)) == 0)
-            {
+               if (s->ctx->app_gen_cookie_cb != NULL &&
+                   s->ctx->app_gen_cookie_cb(s, s->d1->cookie, 
+                   &(s->d1->cookie_len)) == 0)
+                       {
                        SSLerr(SSL_F_DTLS1_SEND_HELLO_VERIFY_REQUEST,ERR_R_INTERNAL_ERROR);
-            return 0;
-            }
-        /* else the cookie is assumed to have 
-         * been initialized by the application */
+                       return 0;
+                       }
+               /* else the cookie is assumed to have 
+                * been initialized by the application */
 
+               *(p++) = (unsigned char) s->d1->cookie_len;
                memcpy(p, s->d1->cookie, s->d1->cookie_len);
                p += s->d1->cookie_len;
                msg_len = p - msg;
@@ -672,8 +680,12 @@ int dtls1_send_server_hello(SSL *s)
                /* Do the message type and length last */
                d=p= &(buf[DTLS1_HM_HEADER_LENGTH]);
 
-               *(p++)=s->version>>8;
-               *(p++)=s->version&0xff;
+               if (s->client_version == DTLS1_BAD_VER)
+                       *(p++)=DTLS1_BAD_VER>>8,
+                       *(p++)=DTLS1_BAD_VER&0xff;
+               else
+                       *(p++)=s->version>>8,
+                       *(p++)=s->version&0xff;
 
                /* Random stuff */
                memcpy(p,s->s3->server_random,SSL3_RANDOM_SIZE);
@@ -1088,7 +1100,7 @@ int dtls1_send_certificate_request(SSL *s)
 
                /* XDTLS:  set message header ? */
                msg_len = s->init_num - DTLS1_HM_HEADER_LENGTH;
-               dtls1_set_message_header(s, s->init_buf->data,
+               dtls1_set_message_header(s, (void *)s->init_buf->data,
                        SSL3_MT_CERTIFICATE_REQUEST, msg_len, 0, msg_len);
 
                /* buffer the message to handle re-xmits */
index b377cc5f6b2d29d8c92c57344229842904d48c53..a663cf85f282dc76745a4f6020f5ff8ab95c2baf 100644 (file)
@@ -67,9 +67,8 @@
 extern "C" {
 #endif
 
-#define DTLS1_VERSION                  0x0100
-#define DTLS1_VERSION_MAJOR            0x01
-#define DTLS1_VERSION_MINOR            0x00
+#define DTLS1_VERSION                  0xFEFF
+#define DTLS1_BAD_VER                  0x0100
 
 #define DTLS1_AD_MISSING_HANDSHAKE_MESSAGE    110
 
@@ -83,7 +82,7 @@ extern "C" {
 #define DTLS1_HM_BAD_FRAGMENT                   -2
 #define DTLS1_HM_FRAGMENT_RETRY                 -3
 
-#define DTLS1_CCS_HEADER_LENGTH                  3
+#define DTLS1_CCS_HEADER_LENGTH                  1
 
 #define DTLS1_AL_HEADER_LENGTH                   7
 
index f1867bd2d9a950d6f964fb03cdbca852bb6d24fd..bc918170e10261b1ab990d1a544f251e93851b40 100644 (file)
@@ -223,6 +223,17 @@ static int ssl23_client_hello(SSL *s)
                {
                version = SSL2_VERSION;
                }
+#ifndef OPENSSL_NO_TLSEXT 
+       if (version != SSL2_VERSION)
+               {
+               /* have to disable SSL 2.0 compatibility if we need TLS extensions */
+
+               if (s->tlsext_hostname != NULL)
+                       ssl2_compat = 0;
+               if (s->tlsext_status_type != -1)
+                       ssl2_compat = 0;
+               }
+#endif
 
        buf=(unsigned char *)s->init_buf->data;
        if (s->state == SSL23_ST_CW_CLNT_HELLO_A)
@@ -368,6 +379,13 @@ static int ssl23_client_hello(SSL *s)
                                *(p++)=comp->id;
                                }
                        *(p++)=0; /* Add the NULL method */
+#ifndef OPENSSL_NO_TLSEXT
+                       if ((p = ssl_add_clienthello_tlsext(s, p, buf+SSL3_RT_MAX_PLAIN_LENGTH)) == NULL)
+                               {
+                               SSLerr(SSL_F_SSL23_CLIENT_HELLO,ERR_R_INTERNAL_ERROR);
+                               return -1;
+                               }
+#endif
                        
                        l = p-d;
                        *p = 42;
index ce60de630a7a8425224abbc1094fba0ba304df7b..e2a90a3ca26b923b5045e8844d351c963d12fb28 100644 (file)
@@ -466,11 +466,11 @@ static int get_server_hello(SSL *s)
                        return(-1);
                        }
 
-               sk_SSL_CIPHER_set_cmp_func(sk,ssl_cipher_ptr_id_cmp);
+               (void)sk_SSL_CIPHER_set_cmp_func(sk,ssl_cipher_ptr_id_cmp);
 
                /* get the array of ciphers we will accept */
                cl=SSL_get_ciphers(s);
-               sk_SSL_CIPHER_set_cmp_func(cl,ssl_cipher_ptr_id_cmp);
+               (void)sk_SSL_CIPHER_set_cmp_func(cl,ssl_cipher_ptr_id_cmp);
 
                /*
                 * If server preference flag set, choose the first
index 27d71a2e0952e5e3f15c3d487b534f74c5d9eec0..0daf2b129df3cc36785ad51975cab60a338e08a9 100644 (file)
@@ -607,7 +607,7 @@ static int get_client_hello(SSL *s)
        else
                {
                i=ssl_get_prev_session(s,&(p[s->s2->tmp.cipher_spec_length]),
-                       s->s2->tmp.session_id_length);
+                       s->s2->tmp.session_id_length, NULL);
                if (i == 1)
                        { /* previous session */
                        s->hit=1;
@@ -657,7 +657,7 @@ static int get_client_hello(SSL *s)
                        {
                        if (sk_SSL_CIPHER_find(allow,sk_SSL_CIPHER_value(prio,z)) < 0)
                                {
-                               sk_SSL_CIPHER_delete(prio,z);
+                               (void)sk_SSL_CIPHER_delete(prio,z);
                                z--;
                                }
                        }
index 0f753c7b85c67363ffc0fcb0fa58a1a3ec142f38..a04d60f90c84aa322068f8371a4900a006c71d1e 100644 (file)
 
 static SSL_METHOD *ssl3_get_client_method(int ver);
 static int ca_dn_cmp(const X509_NAME * const *a,const X509_NAME * const *b);
+#ifndef OPENSSL_NO_TLSEXT
+static int ssl3_check_finished(SSL *s);
+#endif
 
 #ifndef OPENSSL_NO_ECDH
 static int curve_id2nid(int curve_id);
@@ -265,15 +268,43 @@ int ssl3_connect(SSL *s)
 
                case SSL3_ST_CR_CERT_A:
                case SSL3_ST_CR_CERT_B:
+#ifndef OPENSSL_NO_TLSEXT
+                       ret=ssl3_check_finished(s);
+                       if (ret <= 0) goto end;
+                       if (ret == 2)
+                               {
+                               s->hit = 1;
+                               if (s->tlsext_ticket_expected)
+                                       s->state=SSL3_ST_CR_SESSION_TICKET_A;
+                               else
+                                       s->state=SSL3_ST_CR_FINISHED_A;
+                               s->init_num=0;
+                               break;
+                               }
+#endif
                        /* Check if it is anon DH/ECDH */
                        if (!(s->s3->tmp.new_cipher->algorithms & SSL_aNULL))
                                {
                                ret=ssl3_get_server_certificate(s);
                                if (ret <= 0) goto end;
+#ifndef OPENSSL_NO_TLSEXT
+                               if (s->tlsext_status_expected)
+                                       s->state=SSL3_ST_CR_CERT_STATUS_A;
+                               else
+                                       s->state=SSL3_ST_CR_KEY_EXCH_A;
+                               }
+                       else
+                               {
+                               skip = 1;
+                               s->state=SSL3_ST_CR_KEY_EXCH_A;
+                               }
+#else
                                }
                        else
                                skip=1;
+
                        s->state=SSL3_ST_CR_KEY_EXCH_A;
+#endif
                        s->init_num=0;
                        break;
 
@@ -417,11 +448,36 @@ int ssl3_connect(SSL *s)
                                }
                        else
                                {
+#ifndef OPENSSL_NO_TLSEXT
+                               /* Allow NewSessionTicket if ticket expected */
+                               if (s->tlsext_ticket_expected)
+                                       s->s3->tmp.next_state=SSL3_ST_CR_SESSION_TICKET_A;
+                               else
+#endif
+                               
                                s->s3->tmp.next_state=SSL3_ST_CR_FINISHED_A;
                                }
                        s->init_num=0;
                        break;
 
+#ifndef OPENSSL_NO_TLSEXT
+               case SSL3_ST_CR_SESSION_TICKET_A:
+               case SSL3_ST_CR_SESSION_TICKET_B:
+                       ret=ssl3_get_new_session_ticket(s);
+                       if (ret <= 0) goto end;
+                       s->state=SSL3_ST_CR_FINISHED_A;
+                       s->init_num=0;
+               break;
+
+               case SSL3_ST_CR_CERT_STATUS_A:
+               case SSL3_ST_CR_CERT_STATUS_B:
+                       ret=ssl3_get_cert_status(s);
+                       if (ret <= 0) goto end;
+                       s->state=SSL3_ST_CR_KEY_EXCH_A;
+                       s->init_num=0;
+               break;
+#endif
+
                case SSL3_ST_CR_FINISHED_A:
                case SSL3_ST_CR_FINISHED_B:
 
@@ -601,7 +657,13 @@ int ssl3_client_hello(SSL *s)
                        }
 #endif
                *(p++)=0; /* Add the NULL method */
-               
+#ifndef OPENSSL_NO_TLSEXT
+               if ((p = ssl_add_clienthello_tlsext(s, p, buf+SSL3_RT_MAX_PLAIN_LENGTH)) == NULL)
+                       {
+                       SSLerr(SSL_F_SSL3_CLIENT_HELLO,ERR_R_INTERNAL_ERROR);
+                       goto err;
+                       }
+#endif         
                l=(p-d);
                d=buf;
                *(d++)=SSL3_MT_CLIENT_HELLO;
@@ -635,7 +697,7 @@ int ssl3_get_server_hello(SSL *s)
                SSL3_ST_CR_SRVR_HELLO_A,
                SSL3_ST_CR_SRVR_HELLO_B,
                -1,
-               300, /* ?? */
+               20000, /* ?? */
                &ok);
 
        if (!ok) return((int)n);
@@ -785,6 +847,24 @@ int ssl3_get_server_hello(SSL *s)
                s->s3->tmp.new_compression=comp;
                }
 #endif
+#ifndef OPENSSL_NO_TLSEXT
+       /* TLS extensions*/
+       if (s->version > SSL3_VERSION)
+               {
+               if (!ssl_parse_serverhello_tlsext(s,&p,d,n, &al))
+                       {
+                       /* 'al' set by ssl_parse_serverhello_tlsext */
+                       SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_PARSE_TLSEXT);
+                       goto f_err; 
+                       }
+               if (ssl_check_serverhello_tlsext(s) <= 0)
+                       {
+                       SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_SERVERHELLO_TLSEXT);
+                               goto err;
+                       }
+               }
+#endif
+
 
        if (p != (d+n))
                {
@@ -1593,6 +1673,143 @@ static int ca_dn_cmp(const X509_NAME * const *a, const X509_NAME * const *b)
        {
        return(X509_NAME_cmp(*a,*b));
        }
+#ifndef OPENSSL_NO_TLSEXT
+int ssl3_get_new_session_ticket(SSL *s)
+       {
+       int ok,al,ret=0, ticklen;
+       long n;
+       const unsigned char *p;
+       unsigned char *d;
+
+       n=s->method->ssl_get_message(s,
+               SSL3_ST_CR_SESSION_TICKET_A,
+               SSL3_ST_CR_SESSION_TICKET_B,
+               -1,
+               16384,
+               &ok);
+
+       if (!ok)
+               return((int)n);
+
+       if (s->s3->tmp.message_type == SSL3_MT_FINISHED)
+               {
+               s->s3->tmp.reuse_message=1;
+               return(1);
+               }
+       if (s->s3->tmp.message_type != SSL3_MT_NEWSESSION_TICKET)
+               {
+               al=SSL_AD_UNEXPECTED_MESSAGE;
+               SSLerr(SSL_F_SSL3_GET_NEW_SESSION_TICKET,SSL_R_BAD_MESSAGE_TYPE);
+               goto f_err;
+               }
+       if (n < 6)
+               {
+               /* need at least ticket_lifetime_hint + ticket length */
+               al = SSL3_AL_FATAL,SSL_AD_DECODE_ERROR;
+               SSLerr(SSL_F_SSL3_GET_NEW_SESSION_TICKET,SSL_R_LENGTH_MISMATCH);
+               goto f_err;
+               }
+       p=d=(unsigned char *)s->init_msg;
+       n2l(p, s->session->tlsext_tick_lifetime_hint);
+       n2s(p, ticklen);
+       /* ticket_lifetime_hint + ticket_length + ticket */
+       if (ticklen + 6 != n)
+               {
+               al = SSL3_AL_FATAL,SSL_AD_DECODE_ERROR;
+               SSLerr(SSL_F_SSL3_GET_NEW_SESSION_TICKET,SSL_R_LENGTH_MISMATCH);
+               goto f_err;
+               }
+       if (s->session->tlsext_tick)
+               {
+               OPENSSL_free(s->session->tlsext_tick);
+               s->session->tlsext_ticklen = 0;
+               }
+       s->session->tlsext_tick = OPENSSL_malloc(ticklen);
+       if (!s->session->tlsext_tick)
+               {
+               SSLerr(SSL_F_SSL3_GET_NEW_SESSION_TICKET,ERR_R_MALLOC_FAILURE);
+               goto err;
+               }
+       memcpy(s->session->tlsext_tick, p, ticklen);
+       s->session->tlsext_ticklen = ticklen;
+       
+       ret=1;
+       return(ret);
+f_err:
+       ssl3_send_alert(s,SSL3_AL_FATAL,al);
+err:
+       return(-1);
+       }
+
+int ssl3_get_cert_status(SSL *s)
+       {
+       int ok, al;
+       unsigned long resplen;
+       long n;
+       const unsigned char *p;
+
+       n=s->method->ssl_get_message(s,
+               SSL3_ST_CR_CERT_STATUS_A,
+               SSL3_ST_CR_CERT_STATUS_B,
+               SSL3_MT_CERTIFICATE_STATUS,
+               16384,
+               &ok);
+
+       if (!ok) return((int)n);
+       if (n < 4)
+               {
+               /* need at least status type + length */
+               al = SSL_AD_DECODE_ERROR;
+               SSLerr(SSL_F_SSL3_GET_CERT_STATUS,SSL_R_LENGTH_MISMATCH);
+               goto f_err;
+               }
+       p = (unsigned char *)s->init_msg;
+       if (*p++ != TLSEXT_STATUSTYPE_ocsp)
+               {
+               al = SSL_AD_DECODE_ERROR;
+               SSLerr(SSL_F_SSL3_GET_CERT_STATUS,SSL_R_UNSUPPORTED_STATUS_TYPE);
+               goto f_err;
+               }
+       n2l3(p, resplen);
+       if (resplen + 4 != n)
+               {
+               al = SSL_AD_DECODE_ERROR;
+               SSLerr(SSL_F_SSL3_GET_CERT_STATUS,SSL_R_LENGTH_MISMATCH);
+               goto f_err;
+               }
+       if (s->tlsext_ocsp_resp)
+               OPENSSL_free(s->tlsext_ocsp_resp);
+       s->tlsext_ocsp_resp = BUF_memdup(p, resplen);
+       if (!s->tlsext_ocsp_resp)
+               {
+               al = SSL_AD_INTERNAL_ERROR;
+               SSLerr(SSL_F_SSL3_GET_CERT_STATUS,ERR_R_MALLOC_FAILURE);
+               goto f_err;
+               }
+       s->tlsext_ocsp_resplen = resplen;
+       if (s->ctx->tlsext_status_cb)
+               {
+               int ret;
+               ret = s->ctx->tlsext_status_cb(s, s->ctx->tlsext_status_arg);
+               if (ret == 0)
+                       {
+                       al = SSL_AD_BAD_CERTIFICATE_STATUS_RESPONSE;
+                       SSLerr(SSL_F_SSL3_GET_CERT_STATUS,SSL_R_INVALID_STATUS_RESPONSE);
+                       goto f_err;
+                       }
+               if (ret < 0)
+                       {
+                       al = SSL_AD_INTERNAL_ERROR;
+                       SSLerr(SSL_F_SSL3_GET_CERT_STATUS,ERR_R_MALLOC_FAILURE);
+                       goto f_err;
+                       }
+               }
+       return 1;
+f_err:
+       ssl3_send_alert(s,SSL3_AL_FATAL,al);
+       return(-1);
+       }
+#endif
 
 int ssl3_get_server_done(SSL *s)
        {
@@ -2461,3 +2678,33 @@ static int curve_id2nid(int curve_id)
        return nid_list[curve_id];
 }
 #endif
+
+/* Check to see if handshake is full or resumed. Usually this is just a
+ * case of checking to see if a cache hit has occurred. In the case of
+ * session tickets we have to check the next message to be sure.
+ */
+
+#ifndef OPENSSL_NO_TLSEXT
+static int ssl3_check_finished(SSL *s)
+       {
+       int ok;
+       long n;
+       if (!s->session->tlsext_tick)
+               return 1;
+       /* this function is called when we really expect a Certificate
+        * message, so permit appropriate message length */
+       n=s->method->ssl_get_message(s,
+               SSL3_ST_CR_CERT_A,
+               SSL3_ST_CR_CERT_B,
+               -1,
+               s->max_cert_list,
+               &ok);
+       if (!ok) return((int)n);
+       s->s3->tmp.reuse_message = 1;
+       if ((s->s3->tmp.message_type == SSL3_MT_FINISHED)
+               || (s->s3->tmp.message_type == SSL3_MT_NEWSESSION_TICKET))
+               return 2;
+
+       return 1;
+       }
+#endif
index 10087b50ae8cd4de38ebac114c93dde4e43fd325..cbb7b9745ae4615888c6514d2b80595889654595 100644 (file)
@@ -1904,6 +1904,77 @@ long ssl3_ctrl(SSL *s, int cmd, long larg, void *parg)
                }
                break;
 #endif /* !OPENSSL_NO_ECDH */
+#ifndef OPENSSL_NO_TLSEXT
+       case SSL_CTRL_SET_TLSEXT_HOSTNAME:
+               if (larg == TLSEXT_NAMETYPE_host_name)
+                       {
+                       if (s->tlsext_hostname != NULL) 
+                               OPENSSL_free(s->tlsext_hostname);
+                       s->tlsext_hostname = NULL;
+
+                       ret = 1;
+                       if (parg == NULL) 
+                               break;
+                       if (strlen((char *)parg) > TLSEXT_MAXLEN_host_name)
+                               {
+                               SSLerr(SSL_F_SSL3_CTRL, SSL_R_SSL3_EXT_INVALID_SERVERNAME);
+                               return 0;
+                               }
+                       if ((s->tlsext_hostname = BUF_strdup((char *)parg)) == NULL)
+                               {
+                               SSLerr(SSL_F_SSL3_CTRL, ERR_R_INTERNAL_ERROR);
+                               return 0;
+                               }
+                       }
+               else
+                       {
+                       SSLerr(SSL_F_SSL3_CTRL, SSL_R_SSL3_EXT_INVALID_SERVERNAME_TYPE);
+                       return 0;
+                       }
+               break;
+       case SSL_CTRL_SET_TLSEXT_DEBUG_ARG:
+               s->tlsext_debug_arg=parg;
+               ret = 1;
+               break;
+  
+       case SSL_CTRL_SET_TLSEXT_STATUS_REQ_TYPE:
+               s->tlsext_status_type=larg;
+               ret = 1;
+               break;
+
+       case SSL_CTRL_GET_TLSEXT_STATUS_REQ_EXTS:
+               *(STACK_OF(X509_EXTENSION) **)parg = s->tlsext_ocsp_exts;
+               ret = 1;
+               break;
+
+       case SSL_CTRL_SET_TLSEXT_STATUS_REQ_EXTS:
+               s->tlsext_ocsp_exts = parg;
+               ret = 1;
+               break;
+
+       case SSL_CTRL_GET_TLSEXT_STATUS_REQ_IDS:
+               *(STACK_OF(OCSP_RESPID) **)parg = s->tlsext_ocsp_ids;
+               ret = 1;
+               break;
+
+       case SSL_CTRL_SET_TLSEXT_STATUS_REQ_IDS:
+               s->tlsext_ocsp_ids = parg;
+               ret = 1;
+               break;
+
+       case SSL_CTRL_GET_TLSEXT_STATUS_REQ_OCSP_RESP:
+               *(unsigned char **)parg = s->tlsext_ocsp_resp;
+               return s->tlsext_ocsp_resplen;
+               
+       case SSL_CTRL_SET_TLSEXT_STATUS_REQ_OCSP_RESP:
+               if (s->tlsext_ocsp_resp)
+                       OPENSSL_free(s->tlsext_ocsp_resp);
+               s->tlsext_ocsp_resp = parg;
+               s->tlsext_ocsp_resplen = larg;
+               ret = 1;
+               break;
+
+#endif /* !OPENSSL_NO_TLSEXT */
        default:
                break;
                }
@@ -1954,6 +2025,12 @@ long ssl3_callback_ctrl(SSL *s, int cmd, void (*fp)(void))
                s->cert->ecdh_tmp_cb = (EC_KEY *(*)(SSL *, int, int))fp;
                }
                break;
+#endif
+#ifndef OPENSSL_NO_TLSEXT
+       case SSL_CTRL_SET_TLSEXT_DEBUG_CB:
+               s->tlsext_debug_cb=(void (*)(SSL *,int ,int,
+                                       unsigned char *, int, void *))fp;
+               break;
 #endif
        default:
                break;
@@ -2088,6 +2165,42 @@ long ssl3_ctx_ctrl(SSL_CTX *ctx, int cmd, long larg, void *parg)
                }
                break;
 #endif /* !OPENSSL_NO_ECDH */
+#ifndef OPENSSL_NO_TLSEXT
+       case SSL_CTRL_SET_TLSEXT_SERVERNAME_ARG:
+               ctx->tlsext_servername_arg=parg;
+               break;
+       case SSL_CTRL_SET_TLSEXT_TICKET_KEYS:
+       case SSL_CTRL_GET_TLSEXT_TICKET_KEYS:
+               {
+               unsigned char *keys = parg;
+               if (!keys)
+                       return 48;
+               if (larg != 48)
+                       {
+                       SSLerr(SSL_F_SSL3_CTX_CTRL, SSL_R_INVALID_TICKET_KEYS_LENGTH);
+                       return 0;
+                       }
+               if (cmd == SSL_CTRL_SET_TLSEXT_TICKET_KEYS)
+                       {
+                       memcpy(ctx->tlsext_tick_key_name, keys, 16);
+                       memcpy(ctx->tlsext_tick_hmac_key, keys + 16, 16);
+                       memcpy(ctx->tlsext_tick_aes_key, keys + 32, 16);
+                       }
+               else
+                       {
+                       memcpy(keys, ctx->tlsext_tick_key_name, 16);
+                       memcpy(keys + 16, ctx->tlsext_tick_hmac_key, 16);
+                       memcpy(keys + 32, ctx->tlsext_tick_aes_key, 16);
+                       }
+               return 1;
+               }
+  
+       case SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB_ARG:
+               ctx->tlsext_status_arg=parg;
+               return 1;
+               break;
+
+#endif /* !OPENSSL_NO_TLSEXT */
        /* A Thawte special :-) */
        case SSL_CTRL_EXTRA_CHAIN_CERT:
                if (ctx->extra_certs == NULL)
@@ -2132,6 +2245,16 @@ long ssl3_ctx_callback_ctrl(SSL_CTX *ctx, int cmd, void (*fp)(void))
                cert->ecdh_tmp_cb = (EC_KEY *(*)(SSL *, int, int))fp;
                }
                break;
+#endif
+#ifndef OPENSSL_NO_TLSEXT
+       case SSL_CTRL_SET_TLSEXT_SERVERNAME_CB:
+               ctx->tlsext_servername_callback=(int (*)(SSL *,int *,void *))fp;
+               break;
+  
+       case SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB:
+               ctx->tlsext_status_cb=(int (*)(SSL *,void *))fp;
+               break;
+
 #endif
        default:
                return(0);
@@ -2178,6 +2301,7 @@ SSL_CIPHER *ssl3_choose_cipher(SSL *s, STACK_OF(SSL_CIPHER) *clnt,
        SSL_CIPHER *c,*ret=NULL;
        STACK_OF(SSL_CIPHER) *prio, *allow;
        int i,j,ok;
+
        CERT *cert;
        unsigned long alg,mask,emask;
 
index 6c5fdf71b555979265ee0aac2206b72e828fdd3f..827a8c567392cb675fd01b22fb4ecb39a8683dcb 100644 (file)
 #include <openssl/rand.h>
 #include <openssl/objects.h>
 #include <openssl/evp.h>
+#include <openssl/hmac.h>
 #include <openssl/x509.h>
 #ifndef OPENSSL_NO_DH
 #include <openssl/dh.h>
 #include <openssl/md5.h>
 
 static SSL_METHOD *ssl3_get_server_method(int ver);
-
 #ifndef OPENSSL_NO_ECDH
 static int nid2curve_id(int nid);
 #endif
@@ -306,10 +306,24 @@ int ssl3_accept(SSL *s)
                                {
                                ret=ssl3_send_server_certificate(s);
                                if (ret <= 0) goto end;
+#ifndef OPENSSL_NO_TLSEXT
+                               if (s->tlsext_status_expected)
+                                       s->state=SSL3_ST_SW_CERT_STATUS_A;
+                               else
+                                       s->state=SSL3_ST_SW_KEY_EXCH_A;
+                               }
+                       else
+                               {
+                               skip = 1;
+                               s->state=SSL3_ST_SW_KEY_EXCH_A;
+                               }
+#else
                                }
                        else
                                skip=1;
+
                        s->state=SSL3_ST_SW_KEY_EXCH_A;
+#endif
                        s->init_num=0;
                        break;
 
@@ -494,11 +508,34 @@ int ssl3_accept(SSL *s)
                        if (ret <= 0) goto end;
                        if (s->hit)
                                s->state=SSL_ST_OK;
+#ifndef OPENSSL_NO_TLSEXT
+                       else if (s->tlsext_ticket_expected)
+                               s->state=SSL3_ST_SW_SESSION_TICKET_A;
+#endif
                        else
                                s->state=SSL3_ST_SW_CHANGE_A;
                        s->init_num=0;
                        break;
 
+#ifndef OPENSSL_NO_TLSEXT
+               case SSL3_ST_SW_SESSION_TICKET_A:
+               case SSL3_ST_SW_SESSION_TICKET_B:
+                       ret=ssl3_send_newsession_ticket(s);
+                       if (ret <= 0) goto end;
+                       s->state=SSL3_ST_SW_CHANGE_A;
+                       s->init_num=0;
+                       break;
+
+               case SSL3_ST_SW_CERT_STATUS_A:
+               case SSL3_ST_SW_CERT_STATUS_B:
+                       ret=ssl3_send_cert_status(s);
+                       if (ret <= 0) goto end;
+                       s->state=SSL3_ST_SW_KEY_EXCH_A;
+                       s->init_num=0;
+                       break;
+
+#endif
+
                case SSL3_ST_SW_CHANGE_A:
                case SSL3_ST_SW_CHANGE_B:
 
@@ -699,7 +736,8 @@ int ssl3_get_client_hello(SSL *s)
        s->client_version=(((int)p[0])<<8)|(int)p[1];
        p+=2;
 
-       if (s->client_version < s->version)
+       if ((s->version == DTLS1_VERSION && s->client_version > s->version) ||
+           (s->version != DTLS1_VERSION && s->client_version < s->version))
                {
                SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_WRONG_VERSION_NUMBER);
                if ((s->client_version>>8) == SSL3_VERSION_MAJOR) 
@@ -727,14 +765,14 @@ int ssl3_get_client_hello(SSL *s)
         * might be written that become totally unsecure when compiled with
         * an earlier library version)
         */
-       if (j == 0 || (s->new_session && (s->options & SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION)))
+       if ((s->new_session && (s->options & SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION)))
                {
                if (!ssl_get_new_session(s,1))
                        goto err;
                }
        else
                {
-               i=ssl_get_prev_session(s,p,j);
+               i=ssl_get_prev_session(s, p, j, d + n);
                if (i == 1)
                        { /* previous session */
                        s->hit=1;
@@ -750,7 +788,7 @@ int ssl3_get_client_hello(SSL *s)
 
        p+=j;
 
-       if (SSL_version(s) == DTLS1_VERSION)
+       if (s->version == DTLS1_VERSION)
                {
                /* cookie stuff */
                cookie_len = *(p++);
@@ -897,6 +935,22 @@ int ssl3_get_client_hello(SSL *s)
                goto f_err;
                }
 
+#ifndef OPENSSL_NO_TLSEXT
+       /* TLS extensions*/
+       if (s->version > SSL3_VERSION)
+               {
+               if (!ssl_parse_clienthello_tlsext(s,&p,d,n, &al))
+                       {
+                       /* 'al' set by ssl_parse_clienthello_tlsext */
+                       SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_PARSE_TLSEXT);
+                       goto f_err;
+                       }
+               }
+               if (ssl_check_clienthello_tlsext(s) <= 0) {
+                       SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_CLIENTHELLO_TLSEXT);
+                       goto err;
+               }
+#endif
        /* Worst case, we will use the NULL compression, but if we have other
         * options, we will now look for them.  We have i-1 compression
         * algorithms from the client, starting at q. */
@@ -1088,7 +1142,13 @@ int ssl3_send_server_hello(SSL *s)
                else
                        *(p++)=s->s3->tmp.new_compression->id;
 #endif
-
+#ifndef OPENSSL_NO_TLSEXT
+               if ((p = ssl_add_serverhello_tlsext(s, p, buf+SSL3_RT_MAX_PLAIN_LENGTH)) == NULL)
+                       {
+                       SSLerr(SSL_F_SSL3_SEND_SERVER_HELLO,ERR_R_INTERNAL_ERROR);
+                       return -1;
+                       }
+#endif
                /* do the header */
                l=(p-d);
                d=buf;
@@ -1713,8 +1773,9 @@ int ssl3_get_client_key_exchange(SSL *s)
                        rsa=pkey->pkey.rsa;
                        }
 
-               /* TLS */
-               if (s->version > SSL3_VERSION)
+               /* TLS and [incidentally] DTLS, including pre-0.9.8f */
+               if (s->version > SSL3_VERSION &&
+                   s->client_version != DTLS1_BAD_VER)
                        {
                        n2s(p,i);
                        if (n != i+2)
@@ -2617,3 +2678,125 @@ static int nid2curve_id(int nid)
        }
 }
 #endif
+#ifndef OPENSSL_NO_TLSEXT
+int ssl3_send_newsession_ticket(SSL *s)
+       {
+       if (s->state == SSL3_ST_SW_SESSION_TICKET_A)
+               {
+               unsigned char *p, *senc, *macstart;
+               int len, slen;
+               unsigned int hlen;
+               EVP_CIPHER_CTX ctx;
+               HMAC_CTX hctx;
+
+               /* get session encoding length */
+               slen = i2d_SSL_SESSION(s->session, NULL);
+               /* Some length values are 16 bits, so forget it if session is
+                * too long
+                */
+               if (slen > 0xFF00)
+                       return -1;
+               /* Grow buffer if need be: the length calculation is as
+                * follows 1 (size of message name) + 3 (message length
+                * bytes) + 4 (ticket lifetime hint) + 2 (ticket length) +
+                * 16 (key name) + max_iv_len (iv length) +
+                * session_length + max_enc_block_size (max encrypted session
+                * length) + max_md_size (HMAC).
+                */
+               if (!BUF_MEM_grow(s->init_buf,
+                       26 + EVP_MAX_IV_LENGTH + EVP_MAX_BLOCK_LENGTH +
+                       EVP_MAX_MD_SIZE + slen))
+                       return -1;
+               senc = OPENSSL_malloc(slen);
+               if (!senc)
+                       return -1;
+               p = senc;
+               i2d_SSL_SESSION(s->session, &p);
+
+               p=(unsigned char *)s->init_buf->data;
+               /* do the header */
+               *(p++)=SSL3_MT_NEWSESSION_TICKET;
+               /* Skip message length for now */
+               p += 3;
+               l2n(s->session->tlsext_tick_lifetime_hint, p);
+               /* Skip ticket length for now */
+               p += 2;
+               /* Output key name */
+               macstart = p;
+               memcpy(p, s->ctx->tlsext_tick_key_name, 16);
+               p += 16;
+               /* Generate and output IV */
+               RAND_pseudo_bytes(p, 16);
+               EVP_CIPHER_CTX_init(&ctx);
+               /* Encrypt session data */
+               EVP_EncryptInit_ex(&ctx, EVP_aes_128_cbc(), NULL,
+                                       s->ctx->tlsext_tick_aes_key, p);
+               p += 16;
+               EVP_EncryptUpdate(&ctx, p, &len, senc, slen);
+               p += len;
+               EVP_EncryptFinal(&ctx, p, &len);
+               p += len;
+               EVP_CIPHER_CTX_cleanup(&ctx);
+
+               HMAC_CTX_init(&hctx);
+               HMAC_Init_ex(&hctx, s->ctx->tlsext_tick_hmac_key, 16,
+                               tlsext_tick_md(), NULL);
+               HMAC_Update(&hctx, macstart, p - macstart);
+               HMAC_Final(&hctx, p, &hlen);
+               HMAC_CTX_cleanup(&hctx);
+
+               p += hlen;
+               /* Now write out lengths: p points to end of data written */
+               /* Total length */
+               len = p - (unsigned char *)s->init_buf->data;
+               p=(unsigned char *)s->init_buf->data + 1;
+               l2n3(len - 4, p); /* Message length */
+               p += 4;
+               s2n(len - 10, p);  /* Ticket length */
+
+               /* number of bytes to write */
+               s->init_num= len;
+               s->state=SSL3_ST_SW_SESSION_TICKET_B;
+               s->init_off=0;
+               OPENSSL_free(senc);
+               }
+
+       /* SSL3_ST_SW_SESSION_TICKET_B */
+       return(ssl3_do_write(s,SSL3_RT_HANDSHAKE));
+       }
+
+int ssl3_send_cert_status(SSL *s)
+       {
+       if (s->state == SSL3_ST_SW_CERT_STATUS_A)
+               {
+               unsigned char *p;
+               /* Grow buffer if need be: the length calculation is as
+                * follows 1 (message type) + 3 (message length) +
+                * 1 (ocsp response type) + 3 (ocsp response length)
+                * + (ocsp response)
+                */
+               if (!BUF_MEM_grow(s->init_buf, 8 + s->tlsext_ocsp_resplen))
+                       return -1;
+
+               p=(unsigned char *)s->init_buf->data;
+
+               /* do the header */
+               *(p++)=SSL3_MT_CERTIFICATE_STATUS;
+               /* message length */
+               l2n3(s->tlsext_ocsp_resplen + 4, p);
+               /* status type */
+               *(p++)= s->tlsext_status_type;
+               /* length of OCSP response */
+               l2n3(s->tlsext_ocsp_resplen, p);
+               /* actual response */
+               memcpy(p, s->tlsext_ocsp_resp, s->tlsext_ocsp_resplen);
+               /* number of bytes to write */
+               s->init_num = 8 + s->tlsext_ocsp_resplen;
+               s->state=SSL3_ST_SW_CERT_STATUS_B;
+               s->init_off = 0;
+               }
+
+       /* SSL3_ST_SW_CERT_STATUS_B */
+       return(ssl3_do_write(s,SSL3_RT_HANDSHAKE));
+       }
+#endif
index 3e4c103f1702828c0ed956ffb42a4b9d2d899dfb..439a16b4bb99e7039f1f0d1ee2bf8d4904f45faf 100644 (file)
--- a/ssl/ssl.h
+++ b/ssl/ssl.h
@@ -475,6 +475,13 @@ typedef struct ssl_session_st
        /* These are used to make removal of session-ids more
         * efficient and to implement a maximum cache size. */
        struct ssl_session_st *prev,*next;
+#ifndef OPENSSL_NO_TLSEXT
+       char *tlsext_hostname;
+       /* RFC4507 info */
+       unsigned char *tlsext_tick;     /* Session ticket */
+       size_t  tlsext_ticklen;         /* Session ticket length */     
+       long tlsext_tick_lifetime_hint; /* Session lifetime hint in seconds */
+#endif
        } SSL_SESSION;
 
 
@@ -503,6 +510,8 @@ typedef struct ssl_session_st
 #define SSL_OP_NO_QUERY_MTU                 0x00001000L
 /* Turn on Cookie Exchange (on relevant for servers) */
 #define SSL_OP_COOKIE_EXCHANGE              0x00002000L
+/* Don't use RFC4507 ticket extension */
+#define SSL_OP_NO_TICKET                   0x00004000L
 
 /* As server, disallow session resumption on renegotiation */
 #define SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION  0x00010000L
@@ -750,6 +759,22 @@ struct ssl_ctx_st
 #endif
 
        int quiet_shutdown;
+
+#ifndef OPENSSL_NO_TLSEXT
+       /* TLS extensions servername callback */
+       int (*tlsext_servername_callback)(SSL*, int *, void *);
+       void *tlsext_servername_arg;
+       /* RFC 4507 session ticket keys */
+       unsigned char tlsext_tick_key_name[16];
+       unsigned char tlsext_tick_hmac_key[16];
+       unsigned char tlsext_tick_aes_key[16];
+  
+       /* certificate status request info */
+       /* Callback for status request */
+       int (*tlsext_status_cb)(SSL *ssl, void *arg);
+       void *tlsext_status_arg;
+#endif
+
        };
 
 #define SSL_SESS_CACHE_OFF                     0x0000
@@ -971,6 +996,37 @@ struct ssl_st
        int first_packet;
        int client_version;     /* what was passed, used for
                                 * SSLv3/TLS rollback check */
+#ifndef OPENSSL_NO_TLSEXT
+       /* TLS extension debug callback */
+       void (*tlsext_debug_cb)(SSL *s, int client_server, int type,
+                                       unsigned char *data, int len,
+                                       void *arg);
+       void *tlsext_debug_arg;
+       char *tlsext_hostname;
+       int servername_done;   /* no further mod of servername 
+                                 0 : call the servername extension callback.
+                                 1 : prepare 2, allow last ack just after in server callback.
+                                 2 : don't call servername callback, no ack in server hello
+                              */
+       /* certificate status request info */
+       /* Status type or -1 if no status type */
+       int tlsext_status_type;
+       /* Expect OCSP CertificateStatus message */
+       int tlsext_status_expected;
+       /* OCSP status request only */
+       STACK_OF(OCSP_RESPID) *tlsext_ocsp_ids;
+       X509_EXTENSIONS *tlsext_ocsp_exts;
+       /* OCSP response received or to be sent */
+       unsigned char *tlsext_ocsp_resp;
+       int tlsext_ocsp_resplen;
+
+       /* RFC4507 session ticket expected to be received or sent */
+       int tlsext_ticket_expected;
+       SSL_CTX * initial_ctx; /* initial ctx, used to store sessions */
+#define session_ctx initial_ctx
+#else
+#define session_ctx ctx
+#endif
        };
 
 #ifdef __cplusplus
@@ -1116,6 +1172,10 @@ size_t SSL_get_peer_finished(const SSL *s, void *buf, size_t count);
 #define SSL_AD_INTERNAL_ERROR          TLS1_AD_INTERNAL_ERROR  /* fatal */
 #define SSL_AD_USER_CANCELLED          TLS1_AD_USER_CANCELLED
 #define SSL_AD_NO_RENEGOTIATION                TLS1_AD_NO_RENEGOTIATION
+#define SSL_AD_UNSUPPORTED_EXTENSION   TLS1_AD_UNSUPPORTED_EXTENSION
+#define SSL_AD_CERTIFICATE_UNOBTAINABLE TLS1_AD_CERTIFICATE_UNOBTAINABLE
+#define SSL_AD_UNRECOGNIZED_NAME       TLS1_AD_UNRECOGNIZED_NAME
+#define SSL_AD_BAD_CERTIFICATE_STATUS_RESPONSE TLS1_AD_BAD_CERTIFICATE_STATUS_RESPONSE
 
 #define SSL_ERROR_NONE                 0
 #define SSL_ERROR_SSL                  1
@@ -1174,6 +1234,27 @@ size_t SSL_get_peer_finished(const SSL *s, void *buf, size_t count);
 #define SSL_CTRL_GET_MAX_CERT_LIST             50
 #define SSL_CTRL_SET_MAX_CERT_LIST             51
 
+/* see tls1.h for macros based on these */
+#ifndef OPENSSL_NO_TLSEXT
+#define SSL_CTRL_SET_TLSEXT_SERVERNAME_CB      53
+#define SSL_CTRL_SET_TLSEXT_SERVERNAME_ARG     54
+#define SSL_CTRL_SET_TLSEXT_HOSTNAME           55
+#define SSL_CTRL_SET_TLSEXT_DEBUG_CB           56
+#define SSL_CTRL_SET_TLSEXT_DEBUG_ARG          57
+#define SSL_CTRL_GET_TLSEXT_TICKET_KEYS                58
+#define SSL_CTRL_SET_TLSEXT_TICKET_KEYS                59
+
+#define SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB      63
+#define SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB_ARG  64
+#define SSL_CTRL_SET_TLSEXT_STATUS_REQ_TYPE    65
+#define SSL_CTRL_GET_TLSEXT_STATUS_REQ_EXTS    66
+#define SSL_CTRL_SET_TLSEXT_STATUS_REQ_EXTS    67
+#define SSL_CTRL_GET_TLSEXT_STATUS_REQ_IDS     68
+#define SSL_CTRL_SET_TLSEXT_STATUS_REQ_IDS     69
+#define SSL_CTRL_GET_TLSEXT_STATUS_REQ_OCSP_RESP       70
+#define SSL_CTRL_SET_TLSEXT_STATUS_REQ_OCSP_RESP       71
+#endif
+
 #define SSL_session_reused(ssl) \
        SSL_ctrl((ssl),SSL_CTRL_GET_SESSION_REUSED,0,NULL)
 #define SSL_num_renegotiations(ssl) \
@@ -1446,6 +1527,7 @@ int SSL_CTX_load_verify_locations(SSL_CTX *ctx, const char *CAfile,
 SSL_SESSION *SSL_get_session(const SSL *ssl);
 SSL_SESSION *SSL_get1_session(SSL *ssl); /* obtain a reference count */
 SSL_CTX *SSL_get_SSL_CTX(const SSL *ssl);
+SSL_CTX *SSL_set_SSL_CTX(SSL *ssl, SSL_CTX* ctx);
 void SSL_set_info_callback(SSL *ssl,
                           void (*cb)(const SSL *ssl,int type,int val));
 void (*SSL_get_info_callback(const SSL *ssl))(const SSL *ssl,int type,int val);
@@ -1562,6 +1644,7 @@ void ERR_load_SSL_strings(void);
 #define SSL_F_DTLS1_GET_MESSAGE_FRAGMENT                253
 #define SSL_F_DTLS1_GET_RECORD                          254
 #define SSL_F_DTLS1_OUTPUT_CERT_CHAIN                   255
+#define SSL_F_DTLS1_PREPROCESS_FRAGMENT                         277
 #define SSL_F_DTLS1_PROCESS_OUT_OF_SEQ_MESSAGE          256
 #define SSL_F_DTLS1_PROCESS_RECORD                      257
 #define SSL_F_DTLS1_READ_BYTES                          258
@@ -1615,6 +1698,7 @@ void ERR_load_SSL_strings(void);
 #define SSL_F_SSL3_ENC                                  134
 #define SSL_F_SSL3_GENERATE_KEY_BLOCK                   238
 #define SSL_F_SSL3_GET_CERTIFICATE_REQUEST              135
+#define SSL_F_SSL3_GET_CERT_STATUS                      288
 #define SSL_F_SSL3_GET_CERT_VERIFY                      136
 #define SSL_F_SSL3_GET_CLIENT_CERTIFICATE               137
 #define SSL_F_SSL3_GET_CLIENT_HELLO                     138
@@ -1622,10 +1706,12 @@ void ERR_load_SSL_strings(void);
 #define SSL_F_SSL3_GET_FINISHED                                 140
 #define SSL_F_SSL3_GET_KEY_EXCHANGE                     141
 #define SSL_F_SSL3_GET_MESSAGE                          142
+#define SSL_F_SSL3_GET_NEW_SESSION_TICKET               283
 #define SSL_F_SSL3_GET_RECORD                           143
 #define SSL_F_SSL3_GET_SERVER_CERTIFICATE               144
 #define SSL_F_SSL3_GET_SERVER_DONE                      145
 #define SSL_F_SSL3_GET_SERVER_HELLO                     146
+#define SSL_F_SSL3_NEW_SESSION_TICKET                   284
 #define SSL_F_SSL3_OUTPUT_CERT_CHAIN                    147
 #define SSL_F_SSL3_PEEK                                         235
 #define SSL_F_SSL3_READ_BYTES                           148
@@ -1641,8 +1727,10 @@ void ERR_load_SSL_strings(void);
 #define SSL_F_SSL3_SETUP_KEY_BLOCK                      157
 #define SSL_F_SSL3_WRITE_BYTES                          158
 #define SSL_F_SSL3_WRITE_PENDING                        159
+#define SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT                272
 #define SSL_F_SSL_ADD_DIR_CERT_SUBJECTS_TO_STACK        215
 #define SSL_F_SSL_ADD_FILE_CERT_SUBJECTS_TO_STACK       216
+#define SSL_F_SSL_ADD_SERVERHELLO_TLSEXT                273
 #define SSL_F_SSL_BAD_METHOD                            160
 #define SSL_F_SSL_BYTES_TO_CIPHER_LIST                  161
 #define SSL_F_SSL_CERT_DUP                              221
@@ -1650,6 +1738,7 @@ void ERR_load_SSL_strings(void);
 #define SSL_F_SSL_CERT_INSTANTIATE                      214
 #define SSL_F_SSL_CERT_NEW                              162
 #define SSL_F_SSL_CHECK_PRIVATE_KEY                     163
+#define SSL_F_SSL_CHECK_SERVERHELLO_TLSEXT              274
 #define SSL_F_SSL_CIPHER_PROCESS_RULESTR                230
 #define SSL_F_SSL_CIPHER_STRENGTH_SORT                  231
 #define SSL_F_SSL_CLEAR                                         164
@@ -1682,6 +1771,8 @@ void ERR_load_SSL_strings(void);
 #define SSL_F_SSL_LOAD_CLIENT_CA_FILE                   185
 #define SSL_F_SSL_NEW                                   186
 #define SSL_F_SSL_PEEK                                  270
+#define SSL_F_SSL_PREPARE_CLIENTHELLO_TLSEXT            275
+#define SSL_F_SSL_PREPARE_SERVERHELLO_TLSEXT            276
 #define SSL_F_SSL_READ                                  223
 #define SSL_F_SSL_RSA_PRIVATE_DECRYPT                   187
 #define SSL_F_SSL_RSA_PUBLIC_ENCRYPT                    188
@@ -1764,6 +1855,7 @@ void ERR_load_SSL_strings(void);
 #define SSL_R_CIPHER_CODE_WRONG_LENGTH                  137
 #define SSL_R_CIPHER_OR_HASH_UNAVAILABLE                138
 #define SSL_R_CIPHER_TABLE_SRC_ERROR                    139
+#define SSL_R_CLIENTHELLO_TLSEXT                        157
 #define SSL_R_COMPRESSED_LENGTH_TOO_LONG                140
 #define SSL_R_COMPRESSION_FAILURE                       141
 #define SSL_R_COMPRESSION_ID_NOT_WITHIN_PRIVATE_RANGE   307
@@ -1791,6 +1883,8 @@ void ERR_load_SSL_strings(void);
 #define SSL_R_INVALID_CHALLENGE_LENGTH                  158
 #define SSL_R_INVALID_COMMAND                           280
 #define SSL_R_INVALID_PURPOSE                           278
+#define SSL_R_INVALID_STATUS_RESPONSE                   316
+#define SSL_R_INVALID_TICKET_KEYS_LENGTH                275
 #define SSL_R_INVALID_TRUST                             279
 #define SSL_R_KEY_ARG_TOO_LONG                          284
 #define SSL_R_KRB5                                      285
@@ -1848,6 +1942,7 @@ void ERR_load_SSL_strings(void);
 #define SSL_R_OLD_SESSION_CIPHER_NOT_RETURNED           197
 #define SSL_R_ONLY_TLS_ALLOWED_IN_FIPS_MODE             297
 #define SSL_R_PACKET_LENGTH_TOO_LONG                    198
+#define SSL_R_PARSE_TLSEXT                              223
 #define SSL_R_PATH_TOO_LONG                             270
 #define SSL_R_PEER_DID_NOT_RETURN_A_CERTIFICATE                 199
 #define SSL_R_PEER_ERROR                                200
@@ -1871,11 +1966,14 @@ void ERR_load_SSL_strings(void);
 #define SSL_R_REUSE_CERT_LENGTH_NOT_ZERO                216
 #define SSL_R_REUSE_CERT_TYPE_NOT_ZERO                  217
 #define SSL_R_REUSE_CIPHER_LIST_NOT_ZERO                218
+#define SSL_R_SERVERHELLO_TLSEXT                        224
 #define SSL_R_SESSION_ID_CONTEXT_UNINITIALIZED          277
 #define SSL_R_SHORT_READ                                219
 #define SSL_R_SIGNATURE_FOR_NON_SIGNING_CERTIFICATE     220
 #define SSL_R_SSL23_DOING_SESSION_ID_REUSE              221
 #define SSL_R_SSL2_CONNECTION_ID_TOO_LONG               299
+#define SSL_R_SSL3_EXT_INVALID_SERVERNAME               225
+#define SSL_R_SSL3_EXT_INVALID_SERVERNAME_TYPE          226
 #define SSL_R_SSL3_SESSION_ID_TOO_LONG                  300
 #define SSL_R_SSL3_SESSION_ID_TOO_SHORT                         222
 #define SSL_R_SSLV3_ALERT_BAD_CERTIFICATE               1042
@@ -1910,6 +2008,7 @@ void ERR_load_SSL_strings(void);
 #define SSL_R_TLSV1_ALERT_UNKNOWN_CA                    1048
 #define SSL_R_TLSV1_ALERT_USER_CANCELLED                1090
 #define SSL_R_TLS_CLIENT_CERT_REQ_WITH_ANON_CIPHER      232
+#define SSL_R_TLS_INVALID_ECPOINTFORMAT_LIST            227
 #define SSL_R_TLS_PEER_DID_NOT_RESPOND_WITH_CERTIFICATE_LIST 233
 #define SSL_R_TLS_RSA_ENCRYPTED_VALUE_LENGTH_IS_WRONG   234
 #define SSL_R_TRIED_TO_USE_UNSUPPORTED_CIPHER           235
@@ -1941,6 +2040,7 @@ void ERR_load_SSL_strings(void);
 #define SSL_R_UNSUPPORTED_ELLIPTIC_CURVE                315
 #define SSL_R_UNSUPPORTED_PROTOCOL                      258
 #define SSL_R_UNSUPPORTED_SSL_VERSION                   259
+#define SSL_R_UNSUPPORTED_STATUS_TYPE                   329
 #define SSL_R_WRITE_BIO_NOT_SET                                 260
 #define SSL_R_WRONG_CIPHER_RETURNED                     261
 #define SSL_R_WRONG_MESSAGE_TYPE                        262
index bacaff157e5be0f295cc029a1175738ecbe0d485..4b1e2e9834775497d922ab72a7bfc94799398a8d 100644 (file)
@@ -481,6 +481,10 @@ typedef struct ssl3_state_st
 #define SSL3_ST_CR_CHANGE_B            (0x1C1|SSL_ST_CONNECT)
 #define SSL3_ST_CR_FINISHED_A          (0x1D0|SSL_ST_CONNECT)
 #define SSL3_ST_CR_FINISHED_B          (0x1D1|SSL_ST_CONNECT)
+#define SSL3_ST_CR_SESSION_TICKET_A    (0x1E0|SSL_ST_CONNECT)
+#define SSL3_ST_CR_SESSION_TICKET_B    (0x1E1|SSL_ST_CONNECT)
+#define SSL3_ST_CR_CERT_STATUS_A       (0x1F0|SSL_ST_CONNECT)
+#define SSL3_ST_CR_CERT_STATUS_B       (0x1F1|SSL_ST_CONNECT)
 
 /* server */
 /* extra state */
@@ -522,10 +526,15 @@ typedef struct ssl3_state_st
 #define SSL3_ST_SW_CHANGE_B            (0x1D1|SSL_ST_ACCEPT)
 #define SSL3_ST_SW_FINISHED_A          (0x1E0|SSL_ST_ACCEPT)
 #define SSL3_ST_SW_FINISHED_B          (0x1E1|SSL_ST_ACCEPT)
+#define SSL3_ST_SW_SESSION_TICKET_A    (0x1F0|SSL_ST_ACCEPT)
+#define SSL3_ST_SW_SESSION_TICKET_B    (0x1F1|SSL_ST_ACCEPT)
+#define SSL3_ST_SW_CERT_STATUS_A       (0x200|SSL_ST_ACCEPT)
+#define SSL3_ST_SW_CERT_STATUS_B       (0x201|SSL_ST_ACCEPT)
 
 #define SSL3_MT_HELLO_REQUEST                  0
 #define SSL3_MT_CLIENT_HELLO                   1
 #define SSL3_MT_SERVER_HELLO                   2
+#define        SSL3_MT_NEWSESSION_TICKET               4
 #define SSL3_MT_CERTIFICATE                    11
 #define SSL3_MT_SERVER_KEY_EXCHANGE            12
 #define SSL3_MT_CERTIFICATE_REQUEST            13
@@ -533,6 +542,7 @@ typedef struct ssl3_state_st
 #define SSL3_MT_CERTIFICATE_VERIFY             15
 #define SSL3_MT_CLIENT_KEY_EXCHANGE            16
 #define SSL3_MT_FINISHED                       20
+#define SSL3_MT_CERTIFICATE_STATUS             22
 #define DTLS1_MT_HELLO_VERIFY_REQUEST    3
 
 
index d129acc329110b90d1704be92dcca629ab1855c6..6e14f4d834da698cc8b3ff2c9b4eebe918f23090 100644 (file)
@@ -78,6 +78,11 @@ typedef struct ssl_session_asn1_st
        ASN1_INTEGER time;
        ASN1_INTEGER timeout;
        ASN1_INTEGER verify_result;
+#ifndef OPENSSL_NO_TLSEXT
+       ASN1_OCTET_STRING tlsext_hostname;
+       ASN1_INTEGER tlsext_tick_lifetime;
+       ASN1_OCTET_STRING tlsext_tick;
+#endif /* OPENSSL_NO_TLSEXT */
        } SSL_SESSION_ASN1;
 
 int i2d_SSL_SESSION(SSL_SESSION *in, unsigned char **pp)
@@ -86,6 +91,10 @@ int i2d_SSL_SESSION(SSL_SESSION *in, unsigned char **pp)
        int v1=0,v2=0,v3=0,v4=0,v5=0;
        unsigned char buf[4],ibuf1[LSIZE2],ibuf2[LSIZE2];
        unsigned char ibuf3[LSIZE2],ibuf4[LSIZE2],ibuf5[LSIZE2];
+#ifndef OPENSSL_NO_TLSEXT
+       int v6=0,v9=0,v10=0;
+       unsigned char ibuf6[LSIZE2];
+#endif
        long l;
        SSL_SESSION_ASN1 a;
        M_ASN1_I2D_vars(in);
@@ -178,7 +187,33 @@ int i2d_SSL_SESSION(SSL_SESSION *in, unsigned char **pp)
                ASN1_INTEGER_set(&a.verify_result,in->verify_result);
                }
 
-
+#ifndef OPENSSL_NO_TLSEXT
+       if (in->tlsext_hostname)
+                {
+                a.tlsext_hostname.length=strlen(in->tlsext_hostname);
+                a.tlsext_hostname.type=V_ASN1_OCTET_STRING;
+                a.tlsext_hostname.data=(unsigned char *)in->tlsext_hostname;
+                }
+       if (in->tlsext_tick)
+                {
+                a.tlsext_tick.length= in->tlsext_ticklen;
+                a.tlsext_tick.type=V_ASN1_OCTET_STRING;
+                a.tlsext_tick.data=(unsigned char *)in->tlsext_tick;
+               /* If we have a ticket set session ID to empty because
+                * it will be bogus. If liftime hint is -1 treat as a special
+                * case because the session is being used as a container
+                */
+               if (in->tlsext_ticklen && (in->tlsext_tick_lifetime_hint != -1))
+                       a.session_id.length=0;
+                }
+       if (in->tlsext_tick_lifetime_hint > 0)
+               {
+               a.tlsext_tick_lifetime.length=LSIZE2;
+               a.tlsext_tick_lifetime.type=V_ASN1_INTEGER;
+               a.tlsext_tick_lifetime.data=ibuf6;
+               ASN1_INTEGER_set(&a.tlsext_tick_lifetime,in->tlsext_tick_lifetime_hint);
+               }
+#endif /* OPENSSL_NO_TLSEXT */
        M_ASN1_I2D_len(&(a.version),            i2d_ASN1_INTEGER);
        M_ASN1_I2D_len(&(a.ssl_version),        i2d_ASN1_INTEGER);
        M_ASN1_I2D_len(&(a.cipher),             i2d_ASN1_OCTET_STRING);
@@ -200,6 +235,14 @@ int i2d_SSL_SESSION(SSL_SESSION *in, unsigned char **pp)
        if (in->verify_result != X509_V_OK)
                M_ASN1_I2D_len_EXP_opt(&(a.verify_result),i2d_ASN1_INTEGER,5,v5);
 
+#ifndef OPENSSL_NO_TLSEXT
+       if (in->tlsext_tick_lifetime_hint > 0)
+               M_ASN1_I2D_len_EXP_opt(&a.tlsext_tick_lifetime, i2d_ASN1_INTEGER,9,v9);
+       if (in->tlsext_tick)
+               M_ASN1_I2D_len_EXP_opt(&(a.tlsext_tick), i2d_ASN1_OCTET_STRING,10,v10);
+       if (in->tlsext_hostname)
+               M_ASN1_I2D_len_EXP_opt(&(a.tlsext_hostname), i2d_ASN1_OCTET_STRING,6,v6);
+#endif /* OPENSSL_NO_TLSEXT */
        M_ASN1_I2D_seq_total();
 
        M_ASN1_I2D_put(&(a.version),            i2d_ASN1_INTEGER);
@@ -223,6 +266,14 @@ int i2d_SSL_SESSION(SSL_SESSION *in, unsigned char **pp)
                               v4);
        if (in->verify_result != X509_V_OK)
                M_ASN1_I2D_put_EXP_opt(&a.verify_result,i2d_ASN1_INTEGER,5,v5);
+#ifndef OPENSSL_NO_TLSEXT
+       if (in->tlsext_hostname)
+               M_ASN1_I2D_put_EXP_opt(&(a.tlsext_hostname), i2d_ASN1_OCTET_STRING,6,v6);
+       if (in->tlsext_tick_lifetime_hint > 0)
+               M_ASN1_I2D_put_EXP_opt(&a.tlsext_tick_lifetime, i2d_ASN1_INTEGER,9,v9);
+       if (in->tlsext_tick)
+               M_ASN1_I2D_put_EXP_opt(&(a.tlsext_tick), i2d_ASN1_OCTET_STRING,10,v10);
+#endif /* OPENSSL_NO_TLSEXT */
        M_ASN1_I2D_finish();
        }
 
@@ -394,5 +445,56 @@ SSL_SESSION *d2i_SSL_SESSION(SSL_SESSION **a, const unsigned char **pp,
        else
                ret->verify_result=X509_V_OK;
 
+#ifndef OPENSSL_NO_TLSEXT
+       os.length=0;
+       os.data=NULL;
+       M_ASN1_D2I_get_EXP_opt(osp,d2i_ASN1_OCTET_STRING,6);
+       if (os.data)
+               {
+               ret->tlsext_hostname = BUF_strndup((char *)os.data, os.length);
+               OPENSSL_free(os.data);
+               os.data = NULL;
+               os.length = 0;
+               }
+       else
+               ret->tlsext_hostname=NULL;
+       ai.length=0;
+       M_ASN1_D2I_get_EXP_opt(aip,d2i_ASN1_INTEGER,9);
+       if (ai.data != NULL)
+               {
+               ret->tlsext_tick_lifetime_hint=ASN1_INTEGER_get(aip);
+               OPENSSL_free(ai.data); ai.data=NULL; ai.length=0;
+               }
+       else if (ret->tlsext_ticklen && ret->session_id_length)
+               ret->tlsext_tick_lifetime_hint = -1;
+       else
+               ret->tlsext_tick_lifetime_hint = 0;
+       os.length=0;
+       os.data=NULL;
+       M_ASN1_D2I_get_EXP_opt(osp,d2i_ASN1_OCTET_STRING,10);
+       if (os.data)
+               {
+               ret->tlsext_tick = os.data;
+               ret->tlsext_ticklen = os.length;
+               os.data = NULL;
+               os.length = 0;
+#if 0
+               /* There are two ways to detect a resumed ticket sesion.
+                * One is to set a random session ID and then the server
+                * must return a match in ServerHello. This allows the normal
+                * client session ID matching to work.
+                */ 
+               if (ret->session_id_length == 0)
+                       {
+                       ret->session_id_length=SSL3_MAX_SSL_SESSION_ID_LENGTH;
+                       RAND_pseudo_bytes(ret->session_id,
+                                               ret->session_id_length);
+                       }
+#endif
+               }
+       else
+               ret->tlsext_tick=NULL;
+#endif /* OPENSSL_NO_TLSEXT */
+
        M_ASN1_D2I_Finish(a,SSL_SESSION_free,SSL_F_D2I_SSL_SESSION);
        }
index fb080093e550d1b3444fb1edb61525271e3076d7..a32b2d4446452851f3dca5802688830fd89d65fb 100644 (file)
@@ -762,7 +762,7 @@ err:
        if(x != NULL)
                X509_free(x);
        
-       sk_X509_NAME_set_cmp_func(stack,oldcmp);
+       (void)sk_X509_NAME_set_cmp_func(stack,oldcmp);
 
        return ret;
        }
index e7f4d93c7dc4a1f3d40a25daf9aa24b67be6430e..50779c16325b9ce64be20441371b44963825111b 100644 (file)
@@ -1,6 +1,6 @@
 /* ssl/ssl_err.c */
 /* ====================================================================
- * Copyright (c) 1999-2005 The OpenSSL Project.  All rights reserved.
+ * Copyright (c) 1999-2007 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
@@ -87,6 +87,7 @@ static ERR_STRING_DATA SSL_str_functs[]=
 {ERR_FUNC(SSL_F_DTLS1_GET_MESSAGE_FRAGMENT),   "DTLS1_GET_MESSAGE_FRAGMENT"},
 {ERR_FUNC(SSL_F_DTLS1_GET_RECORD),     "DTLS1_GET_RECORD"},
 {ERR_FUNC(SSL_F_DTLS1_OUTPUT_CERT_CHAIN),      "DTLS1_OUTPUT_CERT_CHAIN"},
+{ERR_FUNC(SSL_F_DTLS1_PREPROCESS_FRAGMENT),    "DTLS1_PREPROCESS_FRAGMENT"},
 {ERR_FUNC(SSL_F_DTLS1_PROCESS_OUT_OF_SEQ_MESSAGE),     "DTLS1_PROCESS_OUT_OF_SEQ_MESSAGE"},
 {ERR_FUNC(SSL_F_DTLS1_PROCESS_RECORD), "DTLS1_PROCESS_RECORD"},
 {ERR_FUNC(SSL_F_DTLS1_READ_BYTES),     "DTLS1_READ_BYTES"},
@@ -140,6 +141,7 @@ static ERR_STRING_DATA SSL_str_functs[]=
 {ERR_FUNC(SSL_F_SSL3_ENC),     "SSL3_ENC"},
 {ERR_FUNC(SSL_F_SSL3_GENERATE_KEY_BLOCK),      "SSL3_GENERATE_KEY_BLOCK"},
 {ERR_FUNC(SSL_F_SSL3_GET_CERTIFICATE_REQUEST), "SSL3_GET_CERTIFICATE_REQUEST"},
+{ERR_FUNC(SSL_F_SSL3_GET_CERT_STATUS), "SSL3_GET_CERT_STATUS"},
 {ERR_FUNC(SSL_F_SSL3_GET_CERT_VERIFY), "SSL3_GET_CERT_VERIFY"},
 {ERR_FUNC(SSL_F_SSL3_GET_CLIENT_CERTIFICATE),  "SSL3_GET_CLIENT_CERTIFICATE"},
 {ERR_FUNC(SSL_F_SSL3_GET_CLIENT_HELLO),        "SSL3_GET_CLIENT_HELLO"},
@@ -147,10 +149,12 @@ static ERR_STRING_DATA SSL_str_functs[]=
 {ERR_FUNC(SSL_F_SSL3_GET_FINISHED),    "SSL3_GET_FINISHED"},
 {ERR_FUNC(SSL_F_SSL3_GET_KEY_EXCHANGE),        "SSL3_GET_KEY_EXCHANGE"},
 {ERR_FUNC(SSL_F_SSL3_GET_MESSAGE),     "SSL3_GET_MESSAGE"},
+{ERR_FUNC(SSL_F_SSL3_GET_NEW_SESSION_TICKET),  "SSL3_GET_NEW_SESSION_TICKET"},
 {ERR_FUNC(SSL_F_SSL3_GET_RECORD),      "SSL3_GET_RECORD"},
 {ERR_FUNC(SSL_F_SSL3_GET_SERVER_CERTIFICATE),  "SSL3_GET_SERVER_CERTIFICATE"},
 {ERR_FUNC(SSL_F_SSL3_GET_SERVER_DONE), "SSL3_GET_SERVER_DONE"},
 {ERR_FUNC(SSL_F_SSL3_GET_SERVER_HELLO),        "SSL3_GET_SERVER_HELLO"},
+{ERR_FUNC(SSL_F_SSL3_NEW_SESSION_TICKET),      "SSL3_NEW_SESSION_TICKET"},
 {ERR_FUNC(SSL_F_SSL3_OUTPUT_CERT_CHAIN),       "SSL3_OUTPUT_CERT_CHAIN"},
 {ERR_FUNC(SSL_F_SSL3_PEEK),    "SSL3_PEEK"},
 {ERR_FUNC(SSL_F_SSL3_READ_BYTES),      "SSL3_READ_BYTES"},
@@ -166,8 +170,10 @@ static ERR_STRING_DATA SSL_str_functs[]=
 {ERR_FUNC(SSL_F_SSL3_SETUP_KEY_BLOCK), "SSL3_SETUP_KEY_BLOCK"},
 {ERR_FUNC(SSL_F_SSL3_WRITE_BYTES),     "SSL3_WRITE_BYTES"},
 {ERR_FUNC(SSL_F_SSL3_WRITE_PENDING),   "SSL3_WRITE_PENDING"},
+{ERR_FUNC(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT),   "SSL_ADD_CLIENTHELLO_TLSEXT"},
 {ERR_FUNC(SSL_F_SSL_ADD_DIR_CERT_SUBJECTS_TO_STACK),   "SSL_add_dir_cert_subjects_to_stack"},
 {ERR_FUNC(SSL_F_SSL_ADD_FILE_CERT_SUBJECTS_TO_STACK),  "SSL_add_file_cert_subjects_to_stack"},
+{ERR_FUNC(SSL_F_SSL_ADD_SERVERHELLO_TLSEXT),   "SSL_ADD_SERVERHELLO_TLSEXT"},
 {ERR_FUNC(SSL_F_SSL_BAD_METHOD),       "SSL_BAD_METHOD"},
 {ERR_FUNC(SSL_F_SSL_BYTES_TO_CIPHER_LIST),     "SSL_BYTES_TO_CIPHER_LIST"},
 {ERR_FUNC(SSL_F_SSL_CERT_DUP), "SSL_CERT_DUP"},
@@ -175,6 +181,7 @@ static ERR_STRING_DATA SSL_str_functs[]=
 {ERR_FUNC(SSL_F_SSL_CERT_INSTANTIATE), "SSL_CERT_INSTANTIATE"},
 {ERR_FUNC(SSL_F_SSL_CERT_NEW), "SSL_CERT_NEW"},
 {ERR_FUNC(SSL_F_SSL_CHECK_PRIVATE_KEY),        "SSL_check_private_key"},
+{ERR_FUNC(SSL_F_SSL_CHECK_SERVERHELLO_TLSEXT), "SSL_CHECK_SERVERHELLO_TLSEXT"},
 {ERR_FUNC(SSL_F_SSL_CIPHER_PROCESS_RULESTR),   "SSL_CIPHER_PROCESS_RULESTR"},
 {ERR_FUNC(SSL_F_SSL_CIPHER_STRENGTH_SORT),     "SSL_CIPHER_STRENGTH_SORT"},
 {ERR_FUNC(SSL_F_SSL_CLEAR),    "SSL_clear"},
@@ -207,6 +214,8 @@ static ERR_STRING_DATA SSL_str_functs[]=
 {ERR_FUNC(SSL_F_SSL_LOAD_CLIENT_CA_FILE),      "SSL_load_client_CA_file"},
 {ERR_FUNC(SSL_F_SSL_NEW),      "SSL_new"},
 {ERR_FUNC(SSL_F_SSL_PEEK),     "SSL_peek"},
+{ERR_FUNC(SSL_F_SSL_PREPARE_CLIENTHELLO_TLSEXT),       "SSL_PREPARE_CLIENTHELLO_TLSEXT"},
+{ERR_FUNC(SSL_F_SSL_PREPARE_SERVERHELLO_TLSEXT),       "SSL_PREPARE_SERVERHELLO_TLSEXT"},
 {ERR_FUNC(SSL_F_SSL_READ),     "SSL_read"},
 {ERR_FUNC(SSL_F_SSL_RSA_PRIVATE_DECRYPT),      "SSL_RSA_PRIVATE_DECRYPT"},
 {ERR_FUNC(SSL_F_SSL_RSA_PUBLIC_ENCRYPT),       "SSL_RSA_PUBLIC_ENCRYPT"},
@@ -292,6 +301,7 @@ static ERR_STRING_DATA SSL_str_reasons[]=
 {ERR_REASON(SSL_R_CIPHER_CODE_WRONG_LENGTH),"cipher code wrong length"},
 {ERR_REASON(SSL_R_CIPHER_OR_HASH_UNAVAILABLE),"cipher or hash unavailable"},
 {ERR_REASON(SSL_R_CIPHER_TABLE_SRC_ERROR),"cipher table src error"},
+{ERR_REASON(SSL_R_CLIENTHELLO_TLSEXT)    ,"clienthello tlsext"},
 {ERR_REASON(SSL_R_COMPRESSED_LENGTH_TOO_LONG),"compressed length too long"},
 {ERR_REASON(SSL_R_COMPRESSION_FAILURE)   ,"compression failure"},
 {ERR_REASON(SSL_R_COMPRESSION_ID_NOT_WITHIN_PRIVATE_RANGE),"compression id not within private range"},
@@ -319,6 +329,8 @@ static ERR_STRING_DATA SSL_str_reasons[]=
 {ERR_REASON(SSL_R_INVALID_CHALLENGE_LENGTH),"invalid challenge length"},
 {ERR_REASON(SSL_R_INVALID_COMMAND)       ,"invalid command"},
 {ERR_REASON(SSL_R_INVALID_PURPOSE)       ,"invalid purpose"},
+{ERR_REASON(SSL_R_INVALID_STATUS_RESPONSE),"invalid status response"},
+{ERR_REASON(SSL_R_INVALID_TICKET_KEYS_LENGTH),"invalid ticket keys length"},
 {ERR_REASON(SSL_R_INVALID_TRUST)         ,"invalid trust"},
 {ERR_REASON(SSL_R_KEY_ARG_TOO_LONG)      ,"key arg too long"},
 {ERR_REASON(SSL_R_KRB5)                  ,"krb5"},
@@ -376,6 +388,7 @@ static ERR_STRING_DATA SSL_str_reasons[]=
 {ERR_REASON(SSL_R_OLD_SESSION_CIPHER_NOT_RETURNED),"old session cipher not returned"},
 {ERR_REASON(SSL_R_ONLY_TLS_ALLOWED_IN_FIPS_MODE),"only tls allowed in fips mode"},
 {ERR_REASON(SSL_R_PACKET_LENGTH_TOO_LONG),"packet length too long"},
+{ERR_REASON(SSL_R_PARSE_TLSEXT)          ,"parse tlsext"},
 {ERR_REASON(SSL_R_PATH_TOO_LONG)         ,"path too long"},
 {ERR_REASON(SSL_R_PEER_DID_NOT_RETURN_A_CERTIFICATE),"peer did not return a certificate"},
 {ERR_REASON(SSL_R_PEER_ERROR)            ,"peer error"},
@@ -399,11 +412,14 @@ static ERR_STRING_DATA SSL_str_reasons[]=
 {ERR_REASON(SSL_R_REUSE_CERT_LENGTH_NOT_ZERO),"reuse cert length not zero"},
 {ERR_REASON(SSL_R_REUSE_CERT_TYPE_NOT_ZERO),"reuse cert type not zero"},
 {ERR_REASON(SSL_R_REUSE_CIPHER_LIST_NOT_ZERO),"reuse cipher list not zero"},
+{ERR_REASON(SSL_R_SERVERHELLO_TLSEXT)    ,"serverhello tlsext"},
 {ERR_REASON(SSL_R_SESSION_ID_CONTEXT_UNINITIALIZED),"session id context uninitialized"},
 {ERR_REASON(SSL_R_SHORT_READ)            ,"short read"},
 {ERR_REASON(SSL_R_SIGNATURE_FOR_NON_SIGNING_CERTIFICATE),"signature for non signing certificate"},
 {ERR_REASON(SSL_R_SSL23_DOING_SESSION_ID_REUSE),"ssl23 doing session id reuse"},
 {ERR_REASON(SSL_R_SSL2_CONNECTION_ID_TOO_LONG),"ssl2 connection id too long"},
+{ERR_REASON(SSL_R_SSL3_EXT_INVALID_SERVERNAME),"ssl3 ext invalid servername"},
+{ERR_REASON(SSL_R_SSL3_EXT_INVALID_SERVERNAME_TYPE),"ssl3 ext invalid servername type"},
 {ERR_REASON(SSL_R_SSL3_SESSION_ID_TOO_LONG),"ssl3 session id too long"},
 {ERR_REASON(SSL_R_SSL3_SESSION_ID_TOO_SHORT),"ssl3 session id too short"},
 {ERR_REASON(SSL_R_SSLV3_ALERT_BAD_CERTIFICATE),"sslv3 alert bad certificate"},
@@ -438,6 +454,7 @@ static ERR_STRING_DATA SSL_str_reasons[]=
 {ERR_REASON(SSL_R_TLSV1_ALERT_UNKNOWN_CA),"tlsv1 alert unknown ca"},
 {ERR_REASON(SSL_R_TLSV1_ALERT_USER_CANCELLED),"tlsv1 alert user cancelled"},
 {ERR_REASON(SSL_R_TLS_CLIENT_CERT_REQ_WITH_ANON_CIPHER),"tls client cert req with anon cipher"},
+{ERR_REASON(SSL_R_TLS_INVALID_ECPOINTFORMAT_LIST),"tls invalid ecpointformat list"},
 {ERR_REASON(SSL_R_TLS_PEER_DID_NOT_RESPOND_WITH_CERTIFICATE_LIST),"tls peer did not respond with certificate list"},
 {ERR_REASON(SSL_R_TLS_RSA_ENCRYPTED_VALUE_LENGTH_IS_WRONG),"tls rsa encrypted value length is wrong"},
 {ERR_REASON(SSL_R_TRIED_TO_USE_UNSUPPORTED_CIPHER),"tried to use unsupported cipher"},
@@ -469,6 +486,7 @@ static ERR_STRING_DATA SSL_str_reasons[]=
 {ERR_REASON(SSL_R_UNSUPPORTED_ELLIPTIC_CURVE),"unsupported elliptic curve"},
 {ERR_REASON(SSL_R_UNSUPPORTED_PROTOCOL)  ,"unsupported protocol"},
 {ERR_REASON(SSL_R_UNSUPPORTED_SSL_VERSION),"unsupported ssl version"},
+{ERR_REASON(SSL_R_UNSUPPORTED_STATUS_TYPE),"unsupported status type"},
 {ERR_REASON(SSL_R_WRITE_BIO_NOT_SET)     ,"write bio not set"},
 {ERR_REASON(SSL_R_WRONG_CIPHER_RETURNED) ,"wrong cipher returned"},
 {ERR_REASON(SSL_R_WRONG_MESSAGE_TYPE)    ,"wrong message type"},
index 946e14990eefd32ef06c7e1d7cfdf1ded1456b8e..3715224531dcf7037784ebc99a81c1262b064b26 100644 (file)
 #include <openssl/objects.h>
 #include <openssl/lhash.h>
 #include <openssl/x509v3.h>
+#include <openssl/rand.h>
+#include <openssl/ocsp.h>
 #ifndef OPENSSL_NO_DH
 #include <openssl/dh.h>
 #endif
@@ -306,7 +308,19 @@ SSL *SSL_new(SSL_CTX *ctx)
 
        CRYPTO_add(&ctx->references,1,CRYPTO_LOCK_SSL_CTX);
        s->ctx=ctx;
-
+#ifndef OPENSSL_NO_TLSEXT
+       s->tlsext_debug_cb = 0;
+       s->tlsext_debug_arg = NULL;
+       s->tlsext_ticket_expected = 0;
+       s->tlsext_status_type = -1;
+       s->tlsext_status_expected = 0;
+       s->tlsext_ocsp_ids = NULL;
+       s->tlsext_ocsp_exts = NULL;
+       s->tlsext_ocsp_resp = NULL;
+       s->tlsext_ocsp_resplen = -1;
+       CRYPTO_add(&ctx->references,1,CRYPTO_LOCK_SSL_CTX);
+       s->initial_ctx=ctx;
+#endif
        s->verify_result=X509_V_OK;
 
        s->method=ctx->method;
@@ -492,7 +506,16 @@ void SSL_free(SSL *s)
        /* Free up if allocated */
 
        if (s->ctx) SSL_CTX_free(s->ctx);
-
+#ifndef OPENSSL_NO_TLSEXT
+       if (s->initial_ctx) SSL_CTX_free(s->initial_ctx);
+       if (s->tlsext_ocsp_exts)
+               sk_X509_EXTENSION_pop_free(s->tlsext_ocsp_exts,
+                                               X509_EXTENSION_free);
+       if (s->tlsext_ocsp_ids)
+               sk_OCSP_RESPID_pop_free(s->tlsext_ocsp_ids, OCSP_RESPID_free);
+       if (s->tlsext_ocsp_resp)
+               OPENSSL_free(s->tlsext_ocsp_resp);
+#endif
        if (s->client_CA != NULL)
                sk_X509_NAME_pop_free(s->client_CA,X509_NAME_free);
 
@@ -1201,7 +1224,6 @@ int SSL_set_cipher_list(SSL *s,const char *str)
 char *SSL_get_shared_ciphers(const SSL *s,char *buf,int len)
        {
        char *p;
-       const char *cp;
        STACK_OF(SSL_CIPHER) *sk;
        SSL_CIPHER *c;
        int i;
@@ -1214,20 +1236,21 @@ char *SSL_get_shared_ciphers(const SSL *s,char *buf,int len)
        sk=s->session->ciphers;
        for (i=0; i<sk_SSL_CIPHER_num(sk); i++)
                {
-               /* Decrement for either the ':' or a '\0' */
-               len--;
+               int n;
+
                c=sk_SSL_CIPHER_value(sk,i);
-               for (cp=c->name; *cp; )
+               n=strlen(c->name);
+               if (n+1 > len)
                        {
-                       if (len-- <= 0)
-                               {
-                               *p='\0';
-                               return(buf);
-                               }
-                       else
-                               *(p++)= *(cp++);
+                       if (p != buf)
+                               --p;
+                       *p='\0';
+                       return buf;
                        }
+               strcpy(p,c->name);
+               p+=n;
                *(p++)=':';
+               len-=n+1;
                }
        p[-1]='\0';
        return(buf);
@@ -1304,6 +1327,29 @@ err:
        return(NULL);
        }
 
+#ifndef OPENSSL_NO_TLSEXT
+/** return a servername extension value if provided in Client Hello, or NULL.
+ * So far, only host_name types are defined (RFC 3546).
+ */
+
+const char *SSL_get_servername(const SSL *s, const int type)
+       {
+       if (type != TLSEXT_NAMETYPE_host_name)
+               return NULL;
+
+       return s->session && !s->tlsext_hostname ?
+               s->session->tlsext_hostname :
+               s->tlsext_hostname;
+       }
+
+int SSL_get_servername_type(const SSL *s)
+       {
+       if (s->session && (!s->tlsext_hostname ? s->session->tlsext_hostname : s->tlsext_hostname))
+               return TLSEXT_NAMETYPE_host_name;
+       return -1;
+       }
+#endif
+
 unsigned long SSL_SESSION_hash(const SSL_SESSION *a)
        {
        unsigned long l;
@@ -1461,6 +1507,20 @@ SSL_CTX *SSL_CTX_new(SSL_METHOD *meth)
        ret->extra_certs=NULL;
        ret->comp_methods=SSL_COMP_get_compression_methods();
 
+#ifndef OPENSSL_NO_TLSEXT
+       ret->tlsext_servername_callback = 0;
+       ret->tlsext_servername_arg = NULL;
+       /* Setup RFC4507 ticket keys */
+       if ((RAND_pseudo_bytes(ret->tlsext_tick_key_name, 16) <= 0)
+               || (RAND_bytes(ret->tlsext_tick_hmac_key, 16) <= 0)
+               || (RAND_bytes(ret->tlsext_tick_aes_key, 16) <= 0))
+               ret->options |= SSL_OP_NO_TICKET;
+
+       ret->tlsext_status_cb = 0;
+       ret->tlsext_status_arg = NULL;
+
+#endif
+
        return(ret);
 err:
        SSLerr(SSL_F_SSL_CTX_NEW,ERR_R_MALLOC_FAILURE);
@@ -2410,6 +2470,24 @@ SSL_CTX *SSL_get_SSL_CTX(const SSL *ssl)
        return(ssl->ctx);
        }
 
+SSL_CTX *SSL_set_SSL_CTX(SSL *ssl, SSL_CTX* ctx)
+       {
+       if (ssl->ctx == ctx)
+               return ssl->ctx;
+#ifndef OPENSSL_NO_TLSEXT
+       if (ctx == NULL)
+               ctx = ssl->initial_ctx;
+#endif
+       if (ssl->cert != NULL)
+               ssl_cert_free(ssl->cert);
+       ssl->cert = ssl_cert_dup(ctx->cert);
+       CRYPTO_add(&ctx->references,1,CRYPTO_LOCK_SSL_CTX);
+       if (ssl->ctx != NULL)
+               SSL_CTX_free(ssl->ctx); /* decrement reference count */
+       ssl->ctx = ctx;
+       return(ssl->ctx);
+       }
+
 #ifndef OPENSSL_NO_STDIO
 int SSL_CTX_set_default_verify_paths(SSL_CTX *ctx)
        {
index c36cafd01dfcac6a948b3ff7429de1b3749911bf..f66fd7df9405b4ef87133111bb91ddd65ef30b1e 100644 (file)
@@ -696,7 +696,7 @@ SSL_METHOD *func_name(void)  \
                ssl3_put_cipher_by_char, \
                ssl3_pending, \
                ssl3_num_ciphers, \
-               ssl3_get_cipher, \
+               dtls1_get_cipher, \
                s_get_meth, \
                dtls1_default_timeout, \
                &DTLSv1_enc_data, \
@@ -717,7 +717,7 @@ SESS_CERT *ssl_sess_cert_new(void);
 void ssl_sess_cert_free(SESS_CERT *sc);
 int ssl_set_peer_cert_type(SESS_CERT *c, int type);
 int ssl_get_new_session(SSL *s, int session);
-int ssl_get_prev_session(SSL *s, unsigned char *session,int len);
+int ssl_get_prev_session(SSL *s, unsigned char *session,int len, const unsigned char *limit);
 int ssl_cipher_id_cmp(const SSL_CIPHER *a,const SSL_CIPHER *b);
 int ssl_cipher_ptr_id_cmp(const SSL_CIPHER * const *ap,
                        const SSL_CIPHER * const *bp);
@@ -777,6 +777,8 @@ SSL_CIPHER *ssl3_get_cipher_by_char(const unsigned char *p);
 int ssl3_put_cipher_by_char(const SSL_CIPHER *c,unsigned char *p);
 void ssl3_init_finished_mac(SSL *s);
 int ssl3_send_server_certificate(SSL *s);
+int ssl3_send_newsession_ticket(SSL *s);
+int ssl3_send_cert_status(SSL *s);
 int ssl3_get_finished(SSL *s,int state_a,int state_b);
 int ssl3_setup_key_block(SSL *s);
 int ssl3_send_change_cipher_spec(SSL *s,int state_a,int state_b);
@@ -861,12 +863,16 @@ void dtls1_get_message_header(unsigned char *data, struct hm_header_st *msg_hdr)
 void dtls1_get_ccs_header(unsigned char *data, struct ccs_header_st *ccs_hdr);
 void dtls1_reset_seq_numbers(SSL *s, int rw);
 long dtls1_default_timeout(void);
+SSL_CIPHER *dtls1_get_cipher(unsigned int u);
+
 
 
 /* some client-only functions */
 int ssl3_client_hello(SSL *s);
 int ssl3_get_server_hello(SSL *s);
 int ssl3_get_certificate_request(SSL *s);
+int ssl3_get_new_session_ticket(SSL *s);
+int ssl3_get_cert_status(SSL *s);
 int ssl3_get_server_done(SSL *s);
 int ssl3_send_client_verify(SSL *s);
 int ssl3_send_client_certificate(SSL *s);
@@ -948,5 +954,24 @@ int check_srvr_ecc_cert_and_alg(X509 *x, SSL_CIPHER *cs);
 
 SSL_COMP *ssl3_comp_find(STACK_OF(SSL_COMP) *sk, int n);
 
+#ifndef OPENSSL_NO_TLSEXT
+unsigned char *ssl_add_clienthello_tlsext(SSL *s, unsigned char *p, unsigned char *limit); 
+unsigned char *ssl_add_serverhello_tlsext(SSL *s, unsigned char *p, unsigned char *limit); 
+int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **data, unsigned char *d, int n, int *al);
+int ssl_parse_serverhello_tlsext(SSL *s, unsigned char **data, unsigned char *d, int n, int *al);
+int ssl_prepare_clienthello_tlsext(SSL *s);
+int ssl_prepare_serverhello_tlsext(SSL *s);
+int ssl_check_clienthello_tlsext(SSL *s);
+int ssl_check_serverhello_tlsext(SSL *s);
+#ifdef OPENSSL_NO_SHA256
+#define tlsext_tick_md EVP_sha1
+#else
+#define tlsext_tick_md EVP_sha256
+#endif
+int tls1_process_ticket(SSL *s, unsigned char *session_id, int len,
+                               const unsigned char *limit, SSL_SESSION **ret);
+EVP_MD_CTX* ssl_replace_hash(EVP_MD_CTX **hash,const EVP_MD *md) ;
+void ssl_clear_hash_ctx(EVP_MD_CTX **hash);
+#endif
 
 #endif
index 5bee2d5619ff403aa642b233b5318aea20407313..ee88be2b88ac98df1466b129f4299f2457e884f3 100644 (file)
@@ -122,6 +122,9 @@ SSL_SESSION *SSL_SESSION_new(void)
        ss->prev=NULL;
        ss->next=NULL;
        ss->compress_meth=0;
+#ifndef OPENSSL_NO_TLSEXT
+       ss->tlsext_hostname = NULL; 
+#endif
        CRYPTO_new_ex_data(CRYPTO_EX_INDEX_SSL_SESSION, ss, &ss->ex_data);
        return(ss);
        }
@@ -216,6 +219,14 @@ int ssl_get_new_session(SSL *s, int session)
                        SSL_SESSION_free(ss);
                        return(0);
                        }
+#ifndef OPENSSL_NO_TLSEXT
+               /* If RFC4507 ticket use empty session ID */
+               if (s->tlsext_ticket_expected)
+                       {
+                       ss->session_id_length = 0;
+                       goto sess_id_done;
+                       }
+#endif
                /* Choose which callback will set the session ID */
                CRYPTO_r_lock(CRYPTO_LOCK_SSL_CTX);
                if(s->generate_session_id)
@@ -257,6 +268,17 @@ int ssl_get_new_session(SSL *s, int session)
                        SSL_SESSION_free(ss);
                        return(0);
                        }
+#ifndef OPENSSL_NO_TLSEXT
+               sess_id_done:
+               if (s->tlsext_hostname) {
+                       ss->tlsext_hostname = BUF_strdup(s->tlsext_hostname);
+                       if (ss->tlsext_hostname == NULL) {
+                               SSLerr(SSL_F_SSL_GET_NEW_SESSION, ERR_R_INTERNAL_ERROR);
+                               SSL_SESSION_free(ss);
+                               return 0;
+                               }
+                       }
+#endif
                }
        else
                {
@@ -278,21 +300,41 @@ int ssl_get_new_session(SSL *s, int session)
        return(1);
        }
 
-int ssl_get_prev_session(SSL *s, unsigned char *session_id, int len)
+int ssl_get_prev_session(SSL *s, unsigned char *session_id, int len,
+                       const unsigned char *limit)
        {
        /* This is used only by servers. */
 
-       SSL_SESSION *ret=NULL,data;
+       SSL_SESSION *ret=NULL;
        int fatal = 0;
-
-       data.ssl_version=s->version;
-       data.session_id_length=len;
+#ifndef OPENSSL_NO_TLSEXT
+       int r;
+#endif
+  
        if (len > SSL_MAX_SSL_SESSION_ID_LENGTH)
                goto err;
-       memcpy(data.session_id,session_id,len);
-
+#ifndef OPENSSL_NO_TLSEXT
+       r = tls1_process_ticket(s, session_id, len, limit, &ret);
+       if (r == -1)
+               {
+               fatal = 1;
+               goto err;
+               }
+       else if (r == 0 || (!ret && !len))
+               goto err;
+       else if (!ret && !(s->session_ctx->session_cache_mode & SSL_SESS_CACHE_NO_INTERNAL_LOOKUP))
+#else
+       if (len == 0)
+               goto err;
        if (!(s->ctx->session_cache_mode & SSL_SESS_CACHE_NO_INTERNAL_LOOKUP))
+#endif
                {
+               SSL_SESSION data;
+               data.ssl_version=s->version;
+               data.session_id_length=len;
+               if (len == 0)
+                       return 0;
+               memcpy(data.session_id,session_id,len);
                CRYPTO_r_lock(CRYPTO_LOCK_SSL_CTX);
                ret=(SSL_SESSION *)lh_retrieve(s->ctx->sessions,&data);
                if (ret != NULL)
@@ -548,6 +590,10 @@ void SSL_SESSION_free(SSL_SESSION *ss)
        if (ss->sess_cert != NULL) ssl_sess_cert_free(ss->sess_cert);
        if (ss->peer != NULL) X509_free(ss->peer);
        if (ss->ciphers != NULL) sk_SSL_CIPHER_free(ss->ciphers);
+#ifndef OPENSSL_NO_TLSEXT
+       if (ss->tlsext_hostname != NULL) OPENSSL_free(ss->tlsext_hostname);
+       if (ss->tlsext_tick != NULL) OPENSSL_free(ss->tlsext_tick);
+#endif
        OPENSSL_cleanse(ss,sizeof(*ss));
        OPENSSL_free(ss);
        }
index 4eb0867155e1633af6815b1aea0dba5225b54afb..06b86750fdb550b1929e91c665c46152bbcb53db 100644 (file)
@@ -151,6 +151,21 @@ int SSL_SESSION_print(BIO *bp, const SSL_SESSION *x)
                        if (BIO_printf(bp,"%02X",x->krb5_client_princ[i]) <= 0) goto err;
                        }
 #endif /* OPENSSL_NO_KRB5 */
+#ifndef OPENSSL_NO_TLSEXT
+       if (x->tlsext_tick_lifetime_hint)
+               {
+               if (BIO_printf(bp,
+                       "\n    TLS session ticket lifetime hint: %ld (seconds)",
+                       x->tlsext_tick_lifetime_hint) <=0)
+                       goto err;
+               }
+       if (x->tlsext_tick)
+               {
+               if (BIO_puts(bp, "\n    TLS session ticket:\n") <= 0) goto err;
+               if (BIO_dump_indent(bp, (char *)x->tlsext_tick, x->tlsext_ticklen, 4) <= 0)
+                       goto err;
+               }
+#endif
 #ifndef OPENSSL_NO_COMP
        if (x->compress_meth != 0)
                {
index 99f78cd60bef63b12006af05f89b44139dda862f..c1518264c8c614eadcd937b3da731977b525afb3 100644 (file)
@@ -740,15 +740,35 @@ int tls1_mac(SSL *ssl, unsigned char *md, int send)
        md_size=EVP_MD_size(hash);
 
        buf[0]=rec->type;
-       buf[1]=TLS1_VERSION_MAJOR;
-       buf[2]=TLS1_VERSION_MINOR;
+       if (ssl->version == DTLS1_VERSION && ssl->client_version == DTLS1_BAD_VER)
+               {
+               buf[1]=TLS1_VERSION_MAJOR;
+               buf[2]=TLS1_VERSION_MINOR;
+               }
+       else    {
+               buf[1]=(unsigned char)(ssl->version>>8);
+               buf[2]=(unsigned char)(ssl->version);
+               }
+
        buf[3]=rec->length>>8;
        buf[4]=rec->length&0xff;
 
        /* I should fix this up TLS TLS TLS TLS TLS XXXXXXXX */
        HMAC_CTX_init(&hmac);
        HMAC_Init_ex(&hmac,mac_sec,EVP_MD_size(hash),hash,NULL);
-       HMAC_Update(&hmac,seq,8);
+
+       if (ssl->version == DTLS1_VERSION && ssl->client_version != DTLS1_BAD_VER)
+               {
+               unsigned char dtlsseq[8],*p=dtlsseq;
+
+               s2n(send?ssl->d1->w_epoch:ssl->d1->r_epoch, p);
+               memcpy (p,&seq[2],6);
+
+               HMAC_Update(&hmac,dtlsseq,8);
+               }
+       else
+               HMAC_Update(&hmac,seq,8);
+
        HMAC_Update(&hmac,buf,5);
        HMAC_Update(&hmac,rec->input,rec->length);
        HMAC_Final(&hmac,md,&md_size);
@@ -765,8 +785,8 @@ printf("rec=");
 {unsigned int z; for (z=0; z<rec->length; z++) printf("%02X ",buf[z]); printf("\n"); }
 #endif
 
-    if ( SSL_version(ssl) != DTLS1_VERSION)
-           {
+       if ( SSL_version(ssl) != DTLS1_VERSION)
+               {
                for (i=7; i>=0; i--)
                        {
                        ++seq[i];
index 1ecbbcb8fb1fb5a4277261628eaf57096c1c4f71..8ff1734dabab7fb87129016d948f721faafb0c0f 100644 (file)
 
 #include <stdio.h>
 #include <openssl/objects.h>
+#include <openssl/evp.h>
+#include <openssl/hmac.h>
+#include <openssl/ocsp.h>
 #include "ssl_locl.h"
 
 const char tls1_version_str[]="TLSv1" OPENSSL_VERSION_PTEXT;
 
+#ifndef OPENSSL_NO_TLSEXT
+static int tls_decrypt_ticket(SSL *s, const unsigned char *tick, int ticklen,
+                               const unsigned char *sess_id, int sesslen,
+                               SSL_SESSION **psess);
+#endif
+
 SSL3_ENC_METHOD TLSv1_enc_data={
        tls1_enc,
        tls1_mac,
@@ -117,3 +126,736 @@ long tls1_callback_ctrl(SSL *s, int cmd, void *(*fp)())
        return(0);
        }
 #endif
+
+#ifndef OPENSSL_NO_TLSEXT
+unsigned char *ssl_add_clienthello_tlsext(SSL *s, unsigned char *p, unsigned char *limit)
+       {
+       int extdatalen=0;
+       unsigned char *ret = p;
+
+       ret+=2;
+
+       if (ret>=limit) return NULL; /* this really never occurs, but ... */
+
+       if (s->tlsext_hostname != NULL)
+               { 
+               /* Add TLS extension servername to the Client Hello message */
+               unsigned long size_str;
+               long lenmax; 
+
+               /* check for enough space.
+                  4 for the servername type and entension length
+                  2 for servernamelist length
+                  1 for the hostname type
+                  2 for hostname length
+                  + hostname length 
+               */
+                  
+               if ((lenmax = limit - ret - 9) < 0 
+               || (size_str = strlen(s->tlsext_hostname)) > (unsigned long)lenmax) 
+                       return NULL;
+                       
+               /* extension type and length */
+               s2n(TLSEXT_TYPE_server_name,ret); 
+               s2n(size_str+5,ret);
+               
+               /* length of servername list */
+               s2n(size_str+3,ret);
+       
+               /* hostname type, length and hostname */
+               *(ret++) = (unsigned char) TLSEXT_NAMETYPE_host_name;
+               s2n(size_str,ret);
+               memcpy(ret, s->tlsext_hostname, size_str);
+               ret+=size_str;
+
+               }
+
+       if (!(SSL_get_options(s) & SSL_OP_NO_TICKET))
+               {
+               int ticklen;
+               if (s->session && s->session->tlsext_tick)
+                       ticklen = s->session->tlsext_ticklen;
+               else
+                       ticklen = 0;
+               /* Check for enough room 2 for extension type, 2 for len
+                * rest for ticket
+                */
+               if (limit - ret - 4 - ticklen < 0)
+                       return NULL;
+               s2n(TLSEXT_TYPE_session_ticket,ret); 
+               s2n(ticklen,ret);
+               if (ticklen)
+                       {
+                       memcpy(ret, s->session->tlsext_tick, ticklen);
+                       ret += ticklen;
+                       }
+               }
+
+       if (s->tlsext_status_type == TLSEXT_STATUSTYPE_ocsp)
+               {
+               int i;
+               long extlen, idlen, itmp;
+               OCSP_RESPID *id;
+
+               idlen = 0;
+               for (i = 0; i < sk_OCSP_RESPID_num(s->tlsext_ocsp_ids); i++)
+                       {
+                       id = sk_OCSP_RESPID_value(s->tlsext_ocsp_ids, i);
+                       itmp = i2d_OCSP_RESPID(id, NULL);
+                       if (itmp <= 0)
+                               return NULL;
+                       idlen += itmp + 2;
+                       }
+
+               if (s->tlsext_ocsp_exts)
+                       {
+                       extlen = i2d_X509_EXTENSIONS(s->tlsext_ocsp_exts, NULL);
+                       if (extlen < 0)
+                               return NULL;
+                       }
+               else
+                       extlen = 0;
+                       
+               if ((long)(limit - ret - 7 - extlen - idlen) < 0) return NULL;
+               s2n(TLSEXT_TYPE_status_request, ret);
+               if (extlen + idlen > 0xFFF0)
+                       return NULL;
+               s2n(extlen + idlen + 5, ret);
+               *(ret++) = TLSEXT_STATUSTYPE_ocsp;
+               s2n(idlen, ret);
+               for (i = 0; i < sk_OCSP_RESPID_num(s->tlsext_ocsp_ids); i++)
+                       {
+                       /* save position of id len */
+                       unsigned char *q = ret;
+                       id = sk_OCSP_RESPID_value(s->tlsext_ocsp_ids, i);
+                       /* skip over id len */
+                       ret += 2;
+                       itmp = i2d_OCSP_RESPID(id, &ret);
+                       /* write id len */
+                       s2n(itmp, q);
+                       }
+               s2n(extlen, ret);
+               if (extlen > 0)
+                       i2d_X509_EXTENSIONS(s->tlsext_ocsp_exts, &ret);
+               }
+
+       if ((extdatalen = ret-p-2)== 0) 
+               return p;
+
+       s2n(extdatalen,p);
+       return ret;
+       }
+
+unsigned char *ssl_add_serverhello_tlsext(SSL *s, unsigned char *p, unsigned char *limit)
+       {
+       int extdatalen=0;
+       unsigned char *ret = p;
+
+       ret+=2;
+       if (ret>=limit) return NULL; /* this really never occurs, but ... */
+
+       if (!s->hit && s->servername_done == 1 && s->session->tlsext_hostname != NULL)
+               { 
+               if (limit - ret - 4 < 0) return NULL; 
+
+               s2n(TLSEXT_TYPE_server_name,ret);
+               s2n(0,ret);
+               }
+       
+       if (s->tlsext_ticket_expected
+               && !(SSL_get_options(s) & SSL_OP_NO_TICKET)) 
+               { 
+               if (limit - ret - 4 < 0) return NULL; 
+               s2n(TLSEXT_TYPE_session_ticket,ret);
+               s2n(0,ret);
+               }
+
+       if (s->tlsext_status_expected)
+               { 
+               if ((long)(limit - ret - 4) < 0) return NULL; 
+               s2n(TLSEXT_TYPE_status_request,ret);
+               s2n(0,ret);
+               }
+
+       if ((extdatalen = ret-p-2)== 0) 
+               return p;
+
+       s2n(extdatalen,p);
+       return ret;
+       }
+
+int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d, int n, int *al)
+       {
+       unsigned short type;
+       unsigned short size;
+       unsigned short len;
+       unsigned char *data = *p;
+       s->servername_done = 0;
+       s->tlsext_status_type = -1;
+
+       if (data >= (d+n-2))
+               return 1;
+       n2s(data,len);
+
+       if (data > (d+n-len)) 
+               return 1;
+
+       while (data <= (d+n-4))
+               {
+               n2s(data,type);
+               n2s(data,size);
+
+               if (data+size > (d+n))
+                       return 1;
+
+               if (s->tlsext_debug_cb)
+                       s->tlsext_debug_cb(s, 0, type, data, size,
+                                               s->tlsext_debug_arg);
+/* The servername extension is treated as follows:
+
+   - Only the hostname type is supported with a maximum length of 255.
+   - The servername is rejected if too long or if it contains zeros,
+     in which case an fatal alert is generated.
+   - The servername field is maintained together with the session cache.
+   - When a session is resumed, the servername call back invoked in order
+     to allow the application to position itself to the right context. 
+   - The servername is acknowledged if it is new for a session or when 
+     it is identical to a previously used for the same session. 
+     Applications can control the behaviour.  They can at any time
+     set a 'desirable' servername for a new SSL object. This can be the
+     case for example with HTTPS when a Host: header field is received and
+     a renegotiation is requested. In this case, a possible servername
+     presented in the new client hello is only acknowledged if it matches
+     the value of the Host: field. 
+   - Applications must  use SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION
+     if they provide for changing an explicit servername context for the session,
+     i.e. when the session has been established with a servername extension. 
+   - On session reconnect, the servername extension may be absent. 
+
+*/      
+
+               if (type == TLSEXT_TYPE_server_name)
+                       {
+                       unsigned char *sdata;
+                       int servname_type;
+                       int dsize; 
+               
+                       if (size < 2) 
+                               {
+                               *al = SSL_AD_DECODE_ERROR;
+                               return 0;
+                               }
+                       n2s(data,dsize);  
+                       size -= 2;
+                       if (dsize > size  ) 
+                               {
+                               *al = SSL_AD_DECODE_ERROR;
+                               return 0;
+                               } 
+
+                       sdata = data;
+                       while (dsize > 3) 
+                               {
+                               servname_type = *(sdata++); 
+                               n2s(sdata,len);
+                               dsize -= 3;
+
+                               if (len > dsize) 
+                                       {
+                                       *al = SSL_AD_DECODE_ERROR;
+                                       return 0;
+                                       }
+                               if (s->servername_done == 0)
+                               switch (servname_type)
+                                       {
+                               case TLSEXT_NAMETYPE_host_name:
+                                       if (s->session->tlsext_hostname == NULL)
+                                               {
+                                               if (len > TLSEXT_MAXLEN_host_name || 
+                                                       ((s->session->tlsext_hostname = OPENSSL_malloc(len+1)) == NULL))
+                                                       {
+                                                       *al = TLS1_AD_UNRECOGNIZED_NAME;
+                                                       return 0;
+                                                       }
+                                               memcpy(s->session->tlsext_hostname, sdata, len);
+                                               s->session->tlsext_hostname[len]='\0';
+                                               if (strlen(s->session->tlsext_hostname) != len) {
+                                                       OPENSSL_free(s->session->tlsext_hostname);
+                                                       *al = TLS1_AD_UNRECOGNIZED_NAME;
+                                                       return 0;
+                                               }
+                                               s->servername_done = 1; 
+
+                                               }
+                                       else 
+                                               s->servername_done = strlen(s->session->tlsext_hostname) == len 
+                                                       && strncmp(s->session->tlsext_hostname, (char *)sdata, len) == 0;
+                                       
+                                       break;
+
+                               default:
+                                       break;
+                                       }
+                                
+                               dsize -= len;
+                               }
+                       if (dsize != 0) 
+                               {
+                               *al = SSL_AD_DECODE_ERROR;
+                               return 0;
+                               }
+
+                       }
+               else if (type == TLSEXT_TYPE_status_request
+                                               && s->ctx->tlsext_status_cb)
+                       {
+               
+                       if (size < 5) 
+                               {
+                               *al = SSL_AD_DECODE_ERROR;
+                               return 0;
+                               }
+
+                       s->tlsext_status_type = *data++;
+                       size--;
+                       if (s->tlsext_status_type == TLSEXT_STATUSTYPE_ocsp)
+                               {
+                               const unsigned char *sdata;
+                               int dsize;
+                               /* Read in responder_id_list */
+                               n2s(data,dsize);
+                               size -= 2;
+                               if (dsize > size  ) 
+                                       {
+                                       *al = SSL_AD_DECODE_ERROR;
+                                       return 0;
+                                       }
+                               while (dsize > 0)
+                                       {
+                                       OCSP_RESPID *id;
+                                       int idsize;
+                                       if (dsize < 4)
+                                               {
+                                               *al = SSL_AD_DECODE_ERROR;
+                                               return 0;
+                                               }
+                                       n2s(data, idsize);
+                                       dsize -= 2 + idsize;
+                                       if (dsize < 0)
+                                               {
+                                               *al = SSL_AD_DECODE_ERROR;
+                                               return 0;
+                                               }
+                                       sdata = data;
+                                       data += idsize;
+                                       id = d2i_OCSP_RESPID(NULL,
+                                                               &sdata, idsize);
+                                       if (!id)
+                                               {
+                                               *al = SSL_AD_DECODE_ERROR;
+                                               return 0;
+                                               }
+                                       if (data != sdata)
+                                               {
+                                               OCSP_RESPID_free(id);
+                                               *al = SSL_AD_DECODE_ERROR;
+                                               return 0;
+                                               }
+                                       if (!s->tlsext_ocsp_ids
+                                               && !(s->tlsext_ocsp_ids =
+                                               sk_OCSP_RESPID_new_null()))
+                                               {
+                                               OCSP_RESPID_free(id);
+                                               *al = SSL_AD_INTERNAL_ERROR;
+                                               return 0;
+                                               }
+                                       if (!sk_OCSP_RESPID_push(
+                                                       s->tlsext_ocsp_ids, id))
+                                               {
+                                               OCSP_RESPID_free(id);
+                                               *al = SSL_AD_INTERNAL_ERROR;
+                                               return 0;
+                                               }
+                                       }
+
+                               /* Read in request_extensions */
+                               n2s(data,dsize);
+                               size -= 2;
+                               if (dsize > size) 
+                                       {
+                                       *al = SSL_AD_DECODE_ERROR;
+                                       return 0;
+                                       }
+                               sdata = data;
+                               if (dsize > 0)
+                                       {
+                                       s->tlsext_ocsp_exts =
+                                               d2i_X509_EXTENSIONS(NULL,
+                                                       &sdata, dsize);
+                                       if (!s->tlsext_ocsp_exts
+                                               || (data + dsize != sdata))
+                                               {
+                                               *al = SSL_AD_DECODE_ERROR;
+                                               return 0;
+                                               }
+                                       }
+                               }
+                               /* We don't know what to do with any other type
+                               * so ignore it.
+                               */
+                               else
+                                       s->tlsext_status_type = -1;
+                       }
+               /* session ticket processed earlier */
+
+               data+=size;             
+               }
+
+       *p = data;
+       return 1;
+       }
+
+int ssl_parse_serverhello_tlsext(SSL *s, unsigned char **p, unsigned char *d, int n, int *al)
+       {
+       unsigned short type;
+       unsigned short size;
+       unsigned short len;  
+       unsigned char *data = *p;
+
+       int tlsext_servername = 0;
+
+       if (data >= (d+n-2))
+               return 1;
+
+       n2s(data,len);
+
+       while(data <= (d+n-4))
+               {
+               n2s(data,type);
+               n2s(data,size);
+
+               if (data+size > (d+n))
+                       return 1;
+
+               if (s->tlsext_debug_cb)
+                       s->tlsext_debug_cb(s, 1, type, data, size,
+                                               s->tlsext_debug_arg);
+
+               if (type == TLSEXT_TYPE_server_name)
+                       {
+                       if (s->tlsext_hostname == NULL || size > 0)
+                               {
+                               *al = TLS1_AD_UNRECOGNIZED_NAME;
+                               return 0;
+                               }
+                       tlsext_servername = 1;   
+                       }
+               else if (type == TLSEXT_TYPE_session_ticket)
+                       {
+                       if ((SSL_get_options(s) & SSL_OP_NO_TICKET)
+                               || (size > 0))
+                               {
+                               *al = TLS1_AD_UNSUPPORTED_EXTENSION;
+                               return 0;
+                               }
+                       s->tlsext_ticket_expected = 1;
+                       }
+               else if (type == TLSEXT_TYPE_status_request)
+                       {
+                       /* MUST be empty and only sent if we've requested
+                        * a status request message.
+                        */ 
+                       if ((s->tlsext_status_type == -1) || (size > 0))
+                               {
+                               *al = TLS1_AD_UNSUPPORTED_EXTENSION;
+                               return 0;
+                               }
+                       /* Set flag to expect CertificateStatus message */
+                       s->tlsext_status_expected = 1;
+                       }
+
+               data+=size;             
+               }
+
+       if (data != d+n)
+               {
+               *al = SSL_AD_DECODE_ERROR;
+               return 0;
+               }
+
+       if (!s->hit && tlsext_servername == 1)
+               {
+               if (s->tlsext_hostname)
+                       {
+                       if (s->session->tlsext_hostname == NULL)
+                               {
+                               s->session->tlsext_hostname = BUF_strdup(s->tlsext_hostname);   
+                               if (!s->session->tlsext_hostname)
+                                       {
+                                       *al = SSL_AD_UNRECOGNIZED_NAME;
+                                       return 0;
+                                       }
+                               }
+                       else 
+                               {
+                               *al = SSL_AD_DECODE_ERROR;
+                               return 0;
+                               }
+                       }
+               }
+
+       *p = data;
+       return 1;
+       }
+
+int ssl_check_clienthello_tlsext(SSL *s)
+       {
+       int ret=SSL_TLSEXT_ERR_NOACK;
+       int al = SSL_AD_UNRECOGNIZED_NAME;
+
+       if (s->ctx != NULL && s->ctx->tlsext_servername_callback != 0) 
+               ret = s->ctx->tlsext_servername_callback(s, &al, s->ctx->tlsext_servername_arg);
+       else if (s->initial_ctx != NULL && s->initial_ctx->tlsext_servername_callback != 0)             
+               ret = s->initial_ctx->tlsext_servername_callback(s, &al, s->initial_ctx->tlsext_servername_arg);
+
+       /* If status request then ask callback what to do.
+        * Note: this must be called after servername callbacks in case 
+        * the certificate has changed.
+        */
+       if ((s->tlsext_status_type != -1) && s->ctx->tlsext_status_cb)
+               {
+               int r;
+               r = s->ctx->tlsext_status_cb(s, s->ctx->tlsext_status_arg);
+               switch (r)
+                       {
+                       /* We don't want to send a status request response */
+                       case SSL_TLSEXT_ERR_NOACK:
+                               s->tlsext_status_expected = 0;
+                               break;
+                       /* status request response should be sent */
+                       case SSL_TLSEXT_ERR_OK:
+                               if (s->tlsext_ocsp_resp)
+                                       s->tlsext_status_expected = 1;
+                               else
+                                       s->tlsext_status_expected = 0;
+                               break;
+                       /* something bad happened */
+                       case SSL_TLSEXT_ERR_ALERT_FATAL:
+                               ret = SSL_TLSEXT_ERR_ALERT_FATAL;
+                               al = SSL_AD_INTERNAL_ERROR;
+                               goto err;
+                       }
+               }
+       else
+               s->tlsext_status_expected = 0;
+       err:
+       switch (ret)
+               {
+               case SSL_TLSEXT_ERR_ALERT_FATAL:
+                       ssl3_send_alert(s,SSL3_AL_FATAL,al); 
+                       return -1;
+
+               case SSL_TLSEXT_ERR_ALERT_WARNING:
+                       ssl3_send_alert(s,SSL3_AL_WARNING,al);
+                       return 1; 
+                                       
+               case SSL_TLSEXT_ERR_NOACK:
+                       s->servername_done=0;
+                       default:
+               return 1;
+               }
+       }
+
+int ssl_check_serverhello_tlsext(SSL *s)
+       {
+       int ret=SSL_TLSEXT_ERR_NOACK;
+       int al = SSL_AD_UNRECOGNIZED_NAME;
+
+       if (s->ctx != NULL && s->ctx->tlsext_servername_callback != 0) 
+               ret = s->ctx->tlsext_servername_callback(s, &al, s->ctx->tlsext_servername_arg);
+       else if (s->initial_ctx != NULL && s->initial_ctx->tlsext_servername_callback != 0)             
+               ret = s->initial_ctx->tlsext_servername_callback(s, &al, s->initial_ctx->tlsext_servername_arg);
+
+       /* If we've requested certificate status and we wont get one
+        * tell the callback
+        */
+       if ((s->tlsext_status_type != -1) && !(s->tlsext_status_expected)
+                       && s->ctx->tlsext_status_cb)
+               {
+               int r;
+               /* Set resp to NULL, resplen to -1 so callback knows
+                * there is no response.
+                */
+               if (s->tlsext_ocsp_resp)
+                       {
+                       OPENSSL_free(s->tlsext_ocsp_resp);
+                       s->tlsext_ocsp_resp = NULL;
+                       }
+               s->tlsext_ocsp_resplen = -1;
+               r = s->ctx->tlsext_status_cb(s, s->ctx->tlsext_status_arg);
+               if (r == 0)
+                       {
+                       al = SSL_AD_BAD_CERTIFICATE_STATUS_RESPONSE;
+                       ret = SSL_TLSEXT_ERR_ALERT_FATAL;
+                       }
+               if (r < 0)
+                       {
+                       al = SSL_AD_INTERNAL_ERROR;
+                       ret = SSL_TLSEXT_ERR_ALERT_FATAL;
+                       }
+               }
+
+       switch (ret)
+               {
+               case SSL_TLSEXT_ERR_ALERT_FATAL:
+                       ssl3_send_alert(s,SSL3_AL_FATAL,al); 
+                       return -1;
+
+               case SSL_TLSEXT_ERR_ALERT_WARNING:
+                       ssl3_send_alert(s,SSL3_AL_WARNING,al);
+                       return 1; 
+                                       
+               case SSL_TLSEXT_ERR_NOACK:
+                       s->servername_done=0;
+                       default:
+               return 1;
+               }
+       }
+
+/* Since the server cache lookup is done early on in the processing of client
+ * hello and other operations depend on the result we need to handle any TLS
+ * session ticket extension at the same time.
+ */
+
+int tls1_process_ticket(SSL *s, unsigned char *session_id, int len,
+                               const unsigned char *limit, SSL_SESSION **ret)
+       {
+       /* Point after session ID in client hello */
+       const unsigned char *p = session_id + len;
+       unsigned short i;
+       if ((s->version <= SSL3_VERSION) || !limit)
+               return 1;
+       if (p >= limit)
+               return -1;
+       /* Skip past cipher list */
+       n2s(p, i);
+       p+= i;
+       if (p >= limit)
+               return -1;
+       /* Skip past compression algorithm list */
+       i = *(p++);
+       p += i;
+       if (p > limit)
+               return -1;
+       /* Now at start of extensions */
+       if ((p + 2) >= limit)
+               return 1;
+       n2s(p, i);
+       while ((p + 4) <= limit)
+               {
+               unsigned short type, size;
+               n2s(p, type);
+               n2s(p, size);
+               if (p + size > limit)
+                       return 1;
+               if (type == TLSEXT_TYPE_session_ticket)
+                       {
+                       /* If tickets disabled indicate cache miss which will
+                        * trigger a full handshake
+                        */
+                       if (SSL_get_options(s) & SSL_OP_NO_TICKET)
+                               return 0;
+                       /* If zero length not client will accept a ticket
+                        * and indicate cache miss to trigger full handshake
+                        */
+                       if (size == 0)
+                               {
+                               s->tlsext_ticket_expected = 1;
+                               return 0;       /* Cache miss */
+                               }
+                       return tls_decrypt_ticket(s, p, size, session_id, len,
+                                                                       ret);
+                       }
+               p += size;
+               }
+       return 1;
+       }
+
+static int tls_decrypt_ticket(SSL *s, const unsigned char *etick, int eticklen,
+                               const unsigned char *sess_id, int sesslen,
+                               SSL_SESSION **psess)
+       {
+       SSL_SESSION *sess;
+       unsigned char *sdec;
+       const unsigned char *p;
+       int slen, mlen;
+       unsigned char tick_hmac[EVP_MAX_MD_SIZE];
+       HMAC_CTX hctx;
+       EVP_CIPHER_CTX ctx;
+       /* Attempt to process session ticket, first conduct sanity and
+        * integrity checks on ticket.
+        */
+       mlen = EVP_MD_size(tlsext_tick_md());
+       eticklen -= mlen;
+       /* Need at least keyname + iv + some encrypted data */
+       if (eticklen < 48)
+               goto tickerr;
+       /* Check key name matches */
+       if (memcmp(etick, s->ctx->tlsext_tick_key_name, 16))
+               goto tickerr;
+       /* Check HMAC of encrypted ticket */
+       HMAC_CTX_init(&hctx);
+       HMAC_Init_ex(&hctx, s->ctx->tlsext_tick_hmac_key, 16,
+                               tlsext_tick_md(), NULL);
+       HMAC_Update(&hctx, etick, eticklen);
+       HMAC_Final(&hctx, tick_hmac, NULL);
+       HMAC_CTX_cleanup(&hctx);
+       if (memcmp(tick_hmac, etick + eticklen, mlen))
+               goto tickerr;
+       /* Set p to start of IV */
+       p = etick + 16;
+       EVP_CIPHER_CTX_init(&ctx);
+       /* Attempt to decrypt session data */
+       EVP_DecryptInit_ex(&ctx, EVP_aes_128_cbc(), NULL,
+                                       s->ctx->tlsext_tick_aes_key, p);
+       /* Move p after IV to start of encrypted ticket, update length */
+       p += 16;
+       eticklen -= 32;
+       sdec = OPENSSL_malloc(eticklen);
+       if (!sdec)
+               {
+               EVP_CIPHER_CTX_cleanup(&ctx);
+               return -1;
+               }
+       EVP_DecryptUpdate(&ctx, sdec, &slen, p, eticklen);
+       if (EVP_DecryptFinal(&ctx, sdec + slen, &mlen) <= 0)
+               goto tickerr;
+       slen += mlen;
+       EVP_CIPHER_CTX_cleanup(&ctx);
+       p = sdec;
+               
+       sess = d2i_SSL_SESSION(NULL, &p, slen);
+       OPENSSL_free(sdec);
+       if (sess)
+               {
+               /* The session ID if non-empty is used by some clients to
+                * detect that the ticket has been accepted. So we copy it to
+                * the session structure. If it is empty set length to zero
+                * as required by standard.
+                */
+               if (sesslen)
+                       memcpy(sess->session_id, sess_id, sesslen);
+               sess->session_id_length = sesslen;
+               *psess = sess;
+               s->tlsext_ticket_expected = 0;
+               return 1;
+               }
+       /* If session decrypt failure indicate a cache miss and set state to
+        * send a new ticket
+        */
+       tickerr:        
+       s->tlsext_ticket_expected = 1;
+       return 0;
+       }
+
+#endif
index 2b04effeaecb8fdcfbacf88e6a7afe245a08db38..7c3b6a8a85e64b334ad2c9e9e449589d0c8b578a 100644 (file)
@@ -96,6 +96,90 @@ extern "C" {
 #define TLS1_AD_INTERNAL_ERROR         80      /* fatal */
 #define TLS1_AD_USER_CANCELLED         90
 #define TLS1_AD_NO_RENEGOTIATION       100
+/* codes 110-114 are from RFC3546 */
+#define TLS1_AD_UNSUPPORTED_EXTENSION  110
+#define TLS1_AD_CERTIFICATE_UNOBTAINABLE 111
+#define TLS1_AD_UNRECOGNIZED_NAME      112
+#define TLS1_AD_BAD_CERTIFICATE_STATUS_RESPONSE 113
+#define TLS1_AD_BAD_CERTIFICATE_HASH_VALUE 114
+#define TLS1_AD_UNKNOWN_PSK_IDENTITY   115     /* fatal */
+
+/* ExtensionType values from RFC 3546 */
+#define TLSEXT_TYPE_server_name                        0
+#define TLSEXT_TYPE_max_fragment_length                1
+#define TLSEXT_TYPE_client_certificate_url     2
+#define TLSEXT_TYPE_trusted_ca_keys            3
+#define TLSEXT_TYPE_truncated_hmac             4
+#define TLSEXT_TYPE_status_request             5
+#define TLSEXT_TYPE_elliptic_curves            10
+#define TLSEXT_TYPE_ec_point_formats           11
+#define TLSEXT_TYPE_session_ticket             35
+
+/* NameType value from RFC 3546 */
+#define TLSEXT_NAMETYPE_host_name 0
+/* status request value from RFC 3546 */
+#define TLSEXT_STATUSTYPE_ocsp 1
+
+#ifndef OPENSSL_NO_TLSEXT
+
+#define TLSEXT_MAXLEN_host_name 255
+
+const char *SSL_get_servername(const SSL *s, const int type) ;
+int SSL_get_servername_type(const SSL *s) ;
+
+#define SSL_set_tlsext_host_name(s,name) \
+SSL_ctrl(s,SSL_CTRL_SET_TLSEXT_HOSTNAME,TLSEXT_NAMETYPE_host_name,(char *)name)
+
+#define SSL_set_tlsext_debug_callback(ssl, cb) \
+SSL_callback_ctrl(ssl,SSL_CTRL_SET_TLSEXT_DEBUG_CB,(void (*)(void))cb)
+
+#define SSL_set_tlsext_debug_arg(ssl, arg) \
+SSL_ctrl(ssl,SSL_CTRL_SET_TLSEXT_DEBUG_ARG,0, (void *)arg)
+
+#define SSL_set_tlsext_status_type(ssl, type) \
+SSL_ctrl(ssl,SSL_CTRL_SET_TLSEXT_STATUS_REQ_TYPE,type, NULL)
+
+#define SSL_get_tlsext_status_exts(ssl, arg) \
+SSL_ctrl(ssl,SSL_CTRL_GET_TLSEXT_STATUS_REQ_EXTS,0, (void *)arg)
+
+#define SSL_set_tlsext_status_exts(ssl, arg) \
+SSL_ctrl(ssl,SSL_CTRL_SET_TLSEXT_STATUS_REQ_EXTS,0, (void *)arg)
+
+#define SSL_get_tlsext_status_ids(ssl, arg) \
+SSL_ctrl(ssl,SSL_CTRL_GET_TLSEXT_STATUS_REQ_IDS,0, (void *)arg)
+
+#define SSL_set_tlsext_status_ids(ssl, arg) \
+SSL_ctrl(ssl,SSL_CTRL_SET_TLSEXT_STATUS_REQ_IDS,0, (void *)arg)
+
+#define SSL_get_tlsext_status_ocsp_resp(ssl, arg) \
+SSL_ctrl(ssl,SSL_CTRL_GET_TLSEXT_STATUS_REQ_OCSP_RESP,0, (void *)arg)
+
+#define SSL_set_tlsext_status_ocsp_resp(ssl, arg, arglen) \
+SSL_ctrl(ssl,SSL_CTRL_SET_TLSEXT_STATUS_REQ_OCSP_RESP,arglen, (void *)arg)
+
+#define SSL_CTX_set_tlsext_servername_callback(ctx, cb) \
+SSL_CTX_callback_ctrl(ctx,SSL_CTRL_SET_TLSEXT_SERVERNAME_CB,(void (*)(void))cb)
+
+#define SSL_TLSEXT_ERR_OK 0
+#define SSL_TLSEXT_ERR_ALERT_WARNING 1
+#define SSL_TLSEXT_ERR_ALERT_FATAL 2
+#define SSL_TLSEXT_ERR_NOACK 3
+
+#define SSL_CTX_set_tlsext_servername_arg(ctx, arg) \
+SSL_CTX_ctrl(ctx,SSL_CTRL_SET_TLSEXT_SERVERNAME_ARG,0, (void *)arg)
+
+#define SSL_CTX_get_tlsext_ticket_keys(ctx, keys, keylen) \
+       SSL_CTX_ctrl((ctx),SSL_CTRL_GET_TLXEXT_TICKET_KEYS,(keylen),(keys))
+#define SSL_CTX_set_tlsext_ticket_keys(ctx, keys, keylen) \
+       SSL_CTX_ctrl((ctx),SSL_CTRL_SET_TLXEXT_TICKET_KEYS,(keylen),(keys))
+
+#define SSL_CTX_set_tlsext_status_cb(ssl, cb) \
+SSL_CTX_callback_ctrl(ssl,SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB,(void (*)(void))cb)
+
+#define SSL_CTX_set_tlsext_status_arg(ssl, arg) \
+SSL_CTX_ctrl(ssl,SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB_ARG,0, (void *)arg)
+
+#endif
 
 /* Additional TLS ciphersuites from draft-ietf-tls-56-bit-ciphersuites-00.txt
  * (available if TLS1_ALLOW_EXPERIMENTAL_CIPHERSUITES is defined, see
index 6c485d1e2fb12d9a83817e9e026e5fac8656199c..2b2bdb404880590ee6c553884fa333349b712970 100755 (executable)
@@ -37,8 +37,11 @@ foreach $file (sort keys %files) {
     $file=~s/^\.\///;
     push @{$files{$file}},$origfile;
     my $prevdep="";
-    foreach $dep (sort @{$files{$file}}) {
-       $dep=~s/^\.\///;
+
+    # Remove leading ./ before sorting
+    my @deps = map { $_ =~ s/^\.\///; $_ } @{$files{$file}};
+
+    foreach $dep (sort @deps) {
        next if $prevdep eq $dep; # to exterminate duplicates...
        $prevdep = $dep;
        $len=0 if $len+length($dep)+1 >= 80;
index 95daff5c04d452120644c255ebde4a3b8e50996c..f251ac4e5f1a6e89243d4c2bfad5d1046f2263dc 100755 (executable)
@@ -231,6 +231,7 @@ $cflags.=" -DOPENSSL_NO_DH"   if $no_dh;
 $cflags.=" -DOPENSSL_NO_SOCK" if $no_sock;
 $cflags.=" -DOPENSSL_NO_SSL2" if $no_ssl2;
 $cflags.=" -DOPENSSL_NO_SSL3" if $no_ssl3;
+$cflags.=" -DOPENSSL_NO_TLSEXT"  if $no_tlsext;
 $cflags.=" -DOPENSSL_NO_ERR"  if $no_err;
 $cflags.=" -DOPENSSL_NO_KRB5" if $no_krb5;
 $cflags.=" -DOPENSSL_NO_EC"   if $no_ec;
@@ -1283,6 +1284,7 @@ sub read_options
                "gaswin" => \$gaswin,
                "no-ssl2" => \$no_ssl2,
                "no-ssl3" => \$no_ssl3,
+               "no-tlsext" => \$no_tlsext,
                "no-err" => \$no_err,
                "no-sock" => \$no_sock,
                "no-krb5" => \$no_krb5,
index 510a57743cde796aeb2c2b3ecb4ffe605834ce58..fd42083f1a1c201cfbe4a43e5299e89faa47bd26 100755 (executable)
@@ -96,6 +96,8 @@ my @known_algorithms = ( "RC2", "RC4", "RC5", "IDEA", "DES", "BF",
                         "STATIC_ENGINE", "ENGINE", "HW", "GMP",
                         # RFC3779 support 
                         "RFC3779",
+                        # TLS extension support
+                        "TLSEXT",
                         # Deprecated functions
                         "DEPRECATED" );
 
@@ -116,7 +118,7 @@ my $no_rsa; my $no_dsa; my $no_dh; my $no_hmac=0; my $no_aes; my $no_krb5;
 my $no_ec; my $no_ecdsa; my $no_ecdh; my $no_engine; my $no_hw; my $no_camellia;
 my $no_seed;
 my $no_fp_api; my $no_static_engine; my $no_gmp; my $no_deprecated;
-my $no_rfc3779;
+my $no_rfc3779; my $no_tlsext;
 my $fips;
 
 
@@ -196,6 +198,7 @@ foreach (@ARGV, split(/ /, $options))
        elsif (/^no-engine$/)   { $no_engine=1; }
        elsif (/^no-hw$/)       { $no_hw=1; }
        elsif (/^no-gmp$/)      { $no_gmp=1; }
+       elsif (/^no-tlsext$/)   { $no_tlsext=1; }
        elsif (/^no-rfc3779$/)  { $no_rfc3779=1; }
        }
 
@@ -232,6 +235,7 @@ $max_crypto = $max_num;
 
 my $ssl="ssl/ssl.h";
 $ssl.=" ssl/kssl.h";
+$ssl.=" ssl/tls1.h";
 
 my $crypto ="crypto/crypto.h";
 $crypto.=" crypto/o_dir.h";
@@ -1121,6 +1125,7 @@ sub is_valid
                        if ($keyword eq "STATIC_ENGINE" && $no_static_engine) { return 0; }
                        if ($keyword eq "GMP" && $no_gmp) { return 0; }
                        if ($keyword eq "RFC3779" && $no_rfc3779) { return 0; }
+                       if ($keyword eq "TLSEXT" && $no_tlsext) { return 0; }
                        if ($keyword eq "DEPRECATED" && $no_deprecated) { return 0; }
 
                        # Nothing recognise as true
index 91d29e2b870a201a0ff00e43e57afc1c2c61a02a..b27cbb897fd49ff1bab0e71c89321c5ff2ca51d7 100755 (executable)
@@ -3,6 +3,10 @@
 HERE="`echo $0 | sed -e 's|[^/]*$||'`"
 OPENSSL="${HERE}../apps/openssl"
 
+if [ -d "${HERE}../engines" -a "x$OPENSSL_ENGINES" = "x" ]; then
+       OPENSSL_ENGINES="${HERE}../engines"; export OPENSSL_ENGINES
+fi
+
 if [ -x "${OPENSSL}.exe" ]; then
        # The original reason for this script existence is to work around
        # certain caveats in run-time linker behaviour. On Windows platforms
index b424aecc52c5576a36698a8a44df1aa5721a70d6..b3ac136a5657cf0e4d56249d434c5f6ec78e8546 100755 (executable)
@@ -238,3 +238,6 @@ SSL_CTX_set_info_callback               286 EXIST::FUNCTION:
 SSL_CTX_sess_get_new_cb                 287    EXIST::FUNCTION:
 SSL_CTX_get_client_cert_cb              288    EXIST::FUNCTION:
 SSL_CTX_sess_get_remove_cb              289    EXIST::FUNCTION:
+SSL_set_SSL_CTX                         290    EXIST::FUNCTION:
+SSL_get_servername                      291    EXIST::FUNCTION:TLSEXT
+SSL_get_servername_type                 292    EXIST::FUNCTION:TLSEXT