Import OpenSSL-1.0.2h. vendor/OPENSSL
authorPeter Avalos <pavalos@dragonflybsd.org>
Wed, 3 Aug 2016 08:02:32 +0000 (01:02 -0700)
committerPeter Avalos <pavalos@dragonflybsd.org>
Wed, 3 Aug 2016 08:02:32 +0000 (01:02 -0700)
303 files changed:
crypto/openssl/CHANGES
crypto/openssl/NEWS
crypto/openssl/README
crypto/openssl/README.DELETED
crypto/openssl/apps/CA.pl
crypto/openssl/apps/app_rand.c
crypto/openssl/apps/apps.c
crypto/openssl/apps/apps.h
crypto/openssl/apps/ca.c
crypto/openssl/apps/ciphers.c
crypto/openssl/apps/cms.c
crypto/openssl/apps/crl.c
crypto/openssl/apps/dgst.c
crypto/openssl/apps/dhparam.c
crypto/openssl/apps/ecparam.c
crypto/openssl/apps/genrsa.c
crypto/openssl/apps/ocsp.c
crypto/openssl/apps/openssl.cnf
crypto/openssl/apps/pkcs8.c
crypto/openssl/apps/pkeyutl.c
crypto/openssl/apps/req.c
crypto/openssl/apps/rsautl.c
crypto/openssl/apps/s_apps.h
crypto/openssl/apps/s_cb.c
crypto/openssl/apps/s_client.c
crypto/openssl/apps/s_server.c
crypto/openssl/apps/s_socket.c
crypto/openssl/apps/smime.c
crypto/openssl/apps/speed.c
crypto/openssl/apps/verify.c
crypto/openssl/apps/x509.c
crypto/openssl/crypto/aes/aes_wrap.c
crypto/openssl/crypto/aes/asm/aes-586.pl [deleted file]
crypto/openssl/crypto/aes/asm/aes-x86_64.pl
crypto/openssl/crypto/aes/asm/aesni-mb-x86_64.pl [new file with mode: 0644]
crypto/openssl/crypto/aes/asm/aesni-sha1-x86_64.pl
crypto/openssl/crypto/aes/asm/aesni-sha256-x86_64.pl [new file with mode: 0644]
crypto/openssl/crypto/aes/asm/aesni-x86.pl [deleted file]
crypto/openssl/crypto/aes/asm/aesni-x86_64.pl
crypto/openssl/crypto/aes/asm/bsaes-x86_64.pl
crypto/openssl/crypto/aes/asm/vpaes-x86.pl [deleted file]
crypto/openssl/crypto/aes/asm/vpaes-x86_64.pl
crypto/openssl/crypto/asn1/a_gentm.c
crypto/openssl/crypto/asn1/a_time.c
crypto/openssl/crypto/asn1/a_utctm.c
crypto/openssl/crypto/asn1/ameth_lib.c
crypto/openssl/crypto/asn1/asn1.h
crypto/openssl/crypto/asn1/asn1_locl.h
crypto/openssl/crypto/asn1/t_x509.c
crypto/openssl/crypto/asn1/tasn_dec.c
crypto/openssl/crypto/asn1/x_crl.c
crypto/openssl/crypto/asn1/x_x509.c
crypto/openssl/crypto/asn1/x_x509a.c
crypto/openssl/crypto/bf/asm/bf-586.pl [deleted file]
crypto/openssl/crypto/bio/b_dump.c
crypto/openssl/crypto/bio/b_sock.c
crypto/openssl/crypto/bio/bio.h
crypto/openssl/crypto/bio/bio_err.c
crypto/openssl/crypto/bio/bss_acpt.c
crypto/openssl/crypto/bio/bss_conn.c
crypto/openssl/crypto/bio/bss_dgram.c
crypto/openssl/crypto/bio/bss_fd.c
crypto/openssl/crypto/bio/bss_mem.c
crypto/openssl/crypto/bn/asm/bn-586.pl [deleted file]
crypto/openssl/crypto/bn/asm/co-586.pl [deleted file]
crypto/openssl/crypto/bn/asm/modexp512-x86_64.pl [deleted file]
crypto/openssl/crypto/bn/asm/rsaz-avx2.pl [new file with mode: 0755]
crypto/openssl/crypto/bn/asm/rsaz-x86_64.pl [new file with mode: 0755]
crypto/openssl/crypto/bn/asm/x86_64-gcc.c
crypto/openssl/crypto/bn/asm/x86_64-mont.pl
crypto/openssl/crypto/bn/asm/x86_64-mont5.pl
crypto/openssl/crypto/bn/bn.h
crypto/openssl/crypto/bn/bn_asm.c
crypto/openssl/crypto/bn/bn_exp.c
crypto/openssl/crypto/bn/bn_gf2m.c
crypto/openssl/crypto/bn/bn_lcl.h
crypto/openssl/crypto/bn/rsaz_exp.c [new file with mode: 0644]
crypto/openssl/crypto/bn/rsaz_exp.h [new file with mode: 0644]
crypto/openssl/crypto/buffer/buf_str.c
crypto/openssl/crypto/buffer/buffer.h
crypto/openssl/crypto/camellia/asm/cmll-x86.pl [deleted file]
crypto/openssl/crypto/camellia/asm/cmll-x86_64.pl
crypto/openssl/crypto/cast/cast_lcl.h
crypto/openssl/crypto/cmac/cmac.c
crypto/openssl/crypto/cms/cms.h
crypto/openssl/crypto/cms/cms_asn1.c
crypto/openssl/crypto/cms/cms_env.c
crypto/openssl/crypto/cms/cms_err.c
crypto/openssl/crypto/cms/cms_kari.c [new file with mode: 0644]
crypto/openssl/crypto/cms/cms_lcl.h
crypto/openssl/crypto/cms/cms_lib.c
crypto/openssl/crypto/cms/cms_sd.c
crypto/openssl/crypto/cms/cms_smime.c
crypto/openssl/crypto/cryptlib.c
crypto/openssl/crypto/crypto.h
crypto/openssl/crypto/cversion.c
crypto/openssl/crypto/des/asm/crypt586.pl [deleted file]
crypto/openssl/crypto/des/asm/des-586.pl [deleted file]
crypto/openssl/crypto/des/asm/desboth.pl [deleted file]
crypto/openssl/crypto/des/des_locl.h
crypto/openssl/crypto/dh/dh.h
crypto/openssl/crypto/dh/dh_ameth.c
crypto/openssl/crypto/dh/dh_asn1.c
crypto/openssl/crypto/dh/dh_check.c
crypto/openssl/crypto/dh/dh_err.c
crypto/openssl/crypto/dh/dh_kdf.c [new file with mode: 0644]
crypto/openssl/crypto/dh/dh_key.c
crypto/openssl/crypto/dh/dh_pmeth.c
crypto/openssl/crypto/dh/dh_rfc5114.c [new file with mode: 0644]
crypto/openssl/crypto/dsa/dsa.h
crypto/openssl/crypto/dsa/dsa_ameth.c
crypto/openssl/crypto/dsa/dsa_err.c
crypto/openssl/crypto/dsa/dsa_gen.c
crypto/openssl/crypto/dsa/dsa_locl.h
crypto/openssl/crypto/dsa/dsa_ossl.c
crypto/openssl/crypto/dsa/dsa_pmeth.c
crypto/openssl/crypto/dso/dso_lib.c
crypto/openssl/crypto/ebcdic.c
crypto/openssl/crypto/ec/asm/ecp_nistz256-avx2.pl [new file with mode: 0755]
crypto/openssl/crypto/ec/asm/ecp_nistz256-x86_64.pl [new file with mode: 0755]
crypto/openssl/crypto/ec/ec.h
crypto/openssl/crypto/ec/ec2_smpl.c
crypto/openssl/crypto/ec/ec_ameth.c
crypto/openssl/crypto/ec/ec_curve.c
crypto/openssl/crypto/ec/ec_cvt.c
crypto/openssl/crypto/ec/ec_err.c
crypto/openssl/crypto/ec/ec_key.c
crypto/openssl/crypto/ec/ec_lcl.h
crypto/openssl/crypto/ec/ec_lib.c
crypto/openssl/crypto/ec/ec_pmeth.c
crypto/openssl/crypto/ec/eck_prn.c
crypto/openssl/crypto/ec/ecp_nistp224.c
crypto/openssl/crypto/ec/ecp_nistp256.c
crypto/openssl/crypto/ec/ecp_nistp521.c
crypto/openssl/crypto/ec/ecp_nistz256.c [new file with mode: 0644]
crypto/openssl/crypto/ec/ecp_nistz256_table.c [new file with mode: 0644]
crypto/openssl/crypto/ecdh/ecdh.h
crypto/openssl/crypto/ecdh/ech_kdf.c [copied from crypto/openssl/crypto/dsa/dsa_locl.h with 56% similarity]
crypto/openssl/crypto/ecdh/ech_ossl.c
crypto/openssl/crypto/ecdsa/ecdsa.h
crypto/openssl/crypto/ecdsa/ecs_err.c
crypto/openssl/crypto/ecdsa/ecs_lib.c
crypto/openssl/crypto/ecdsa/ecs_locl.h
crypto/openssl/crypto/ecdsa/ecs_ossl.c
crypto/openssl/crypto/engine/eng_all.c
crypto/openssl/crypto/engine/eng_cryptodev.c
crypto/openssl/crypto/engine/eng_dyn.c
crypto/openssl/crypto/engine/eng_rsax.c [deleted file]
crypto/openssl/crypto/engine/engine.h
crypto/openssl/crypto/evp/c_allc.c
crypto/openssl/crypto/evp/digest.c
crypto/openssl/crypto/evp/e_aes.c
crypto/openssl/crypto/evp/e_aes_cbc_hmac_sha1.c
crypto/openssl/crypto/evp/e_aes_cbc_hmac_sha256.c [new file with mode: 0644]
crypto/openssl/crypto/evp/e_camellia.c
crypto/openssl/crypto/evp/e_des.c
crypto/openssl/crypto/evp/e_des3.c
crypto/openssl/crypto/evp/e_null.c
crypto/openssl/crypto/evp/evp.h
crypto/openssl/crypto/evp/evp_enc.c
crypto/openssl/crypto/evp/evp_err.c
crypto/openssl/crypto/evp/evp_fips.c [deleted file]
crypto/openssl/crypto/evp/evp_lib.c
crypto/openssl/crypto/evp/evp_locl.h
crypto/openssl/crypto/evp/m_dss.c
crypto/openssl/crypto/evp/m_dss1.c
crypto/openssl/crypto/evp/m_ecdsa.c
crypto/openssl/crypto/evp/m_sha1.c
crypto/openssl/crypto/evp/m_sigver.c
crypto/openssl/crypto/evp/p_lib.c
crypto/openssl/crypto/evp/pmeth_lib.c
crypto/openssl/crypto/hmac/hm_ameth.c
crypto/openssl/crypto/hmac/hmac.c
crypto/openssl/crypto/md32_common.h
crypto/openssl/crypto/md5/asm/md5-586.pl [deleted file]
crypto/openssl/crypto/md5/md5_locl.h
crypto/openssl/crypto/modes/asm/aesni-gcm-x86_64.pl [new file with mode: 0644]
crypto/openssl/crypto/modes/asm/ghash-x86.pl [deleted file]
crypto/openssl/crypto/modes/asm/ghash-x86_64.pl
crypto/openssl/crypto/modes/cbc128.c
crypto/openssl/crypto/modes/gcm128.c
crypto/openssl/crypto/modes/modes.h
crypto/openssl/crypto/modes/modes_lcl.h
crypto/openssl/crypto/modes/wrap128.c [copied from crypto/openssl/crypto/hmac/hm_ameth.c with 50% similarity]
crypto/openssl/crypto/o_time.c
crypto/openssl/crypto/o_time.h
crypto/openssl/crypto/objects/obj_dat.h
crypto/openssl/crypto/objects/obj_mac.h
crypto/openssl/crypto/objects/obj_xref.h
crypto/openssl/crypto/ocsp/ocsp.h
crypto/openssl/crypto/ocsp/ocsp_ht.c
crypto/openssl/crypto/ocsp/ocsp_lib.c
crypto/openssl/crypto/opensslv.h
crypto/openssl/crypto/ossl_typ.h
crypto/openssl/crypto/pem/pem.h
crypto/openssl/crypto/pem/pem_all.c
crypto/openssl/crypto/pem/pem_err.c
crypto/openssl/crypto/pem/pem_lib.c
crypto/openssl/crypto/pem/pem_pkey.c
crypto/openssl/crypto/perlasm/cbc.pl [deleted file]
crypto/openssl/crypto/perlasm/x86_64-xlate.pl
crypto/openssl/crypto/perlasm/x86asm.pl [deleted file]
crypto/openssl/crypto/perlasm/x86gas.pl [deleted file]
crypto/openssl/crypto/pkcs12/p12_decr.c
crypto/openssl/crypto/pkcs12/p12_p8e.c
crypto/openssl/crypto/pkcs7/pk7_smime.c
crypto/openssl/crypto/rc4/asm/rc4-586.pl [deleted file]
crypto/openssl/crypto/rc4/rc4_enc.c
crypto/openssl/crypto/ripemd/asm/rmd-586.pl [deleted file]
crypto/openssl/crypto/rsa/rsa.h
crypto/openssl/crypto/rsa/rsa_ameth.c
crypto/openssl/crypto/rsa/rsa_asn1.c
crypto/openssl/crypto/rsa/rsa_err.c
crypto/openssl/crypto/rsa/rsa_oaep.c
crypto/openssl/crypto/rsa/rsa_pmeth.c
crypto/openssl/crypto/rsa/rsa_sign.c
crypto/openssl/crypto/sha/asm/sha1-586.pl [deleted file]
crypto/openssl/crypto/sha/asm/sha1-mb-x86_64.pl [new file with mode: 0644]
crypto/openssl/crypto/sha/asm/sha1-x86_64.pl
crypto/openssl/crypto/sha/asm/sha256-586.pl [deleted file]
crypto/openssl/crypto/sha/asm/sha256-mb-x86_64.pl [new file with mode: 0644]
crypto/openssl/crypto/sha/asm/sha512-586.pl [deleted file]
crypto/openssl/crypto/sha/asm/sha512-x86_64.pl
crypto/openssl/crypto/sha/sha512.c
crypto/openssl/crypto/stack/safestack.h
crypto/openssl/crypto/stack/stack.c
crypto/openssl/crypto/stack/stack.h
crypto/openssl/crypto/symhacks.h
crypto/openssl/crypto/ts/ts_rsp_sign.c
crypto/openssl/crypto/ts/ts_rsp_verify.c
crypto/openssl/crypto/ui/ui_openssl.c
crypto/openssl/crypto/whrlpool/asm/wp-mmx.pl [deleted file]
crypto/openssl/crypto/whrlpool/asm/wp-x86_64.pl
crypto/openssl/crypto/x509/vpm_int.h [copied from crypto/openssl/crypto/o_time.h with 78% similarity]
crypto/openssl/crypto/x509/x509.h
crypto/openssl/crypto/x509/x509_cmp.c
crypto/openssl/crypto/x509/x509_err.c
crypto/openssl/crypto/x509/x509_lu.c
crypto/openssl/crypto/x509/x509_set.c
crypto/openssl/crypto/x509/x509_trs.c
crypto/openssl/crypto/x509/x509_txt.c
crypto/openssl/crypto/x509/x509_vfy.c
crypto/openssl/crypto/x509/x509_vfy.h
crypto/openssl/crypto/x509/x509_vpm.c
crypto/openssl/crypto/x509/x_all.c
crypto/openssl/crypto/x509v3/ext_dat.h
crypto/openssl/crypto/x509v3/v3_lib.c
crypto/openssl/crypto/x509v3/v3_purp.c
crypto/openssl/crypto/x509v3/v3_scts.c [new file with mode: 0644]
crypto/openssl/crypto/x509v3/v3_utl.c
crypto/openssl/crypto/x509v3/v3err.c
crypto/openssl/crypto/x509v3/v3nametest.c [new file with mode: 0644]
crypto/openssl/crypto/x509v3/x509v3.h
crypto/openssl/crypto/x86_64cpuid.pl
crypto/openssl/crypto/x86cpuid.pl [deleted file]
crypto/openssl/e_os.h
crypto/openssl/e_os2.h
crypto/openssl/engines/ccgost/gost89.c
crypto/openssl/engines/ccgost/gost_crypt.c
crypto/openssl/engines/ccgost/gost_pmeth.c
crypto/openssl/engines/e_capi.c
crypto/openssl/engines/vendor_defns/hwcryptohook.h
crypto/openssl/ssl/d1_both.c
crypto/openssl/ssl/d1_clnt.c
crypto/openssl/ssl/d1_enc.c [deleted file]
crypto/openssl/ssl/d1_lib.c
crypto/openssl/ssl/d1_meth.c
crypto/openssl/ssl/d1_pkt.c
crypto/openssl/ssl/d1_srtp.c
crypto/openssl/ssl/d1_srvr.c
crypto/openssl/ssl/dtls1.h
crypto/openssl/ssl/s23_clnt.c
crypto/openssl/ssl/s23_srvr.c
crypto/openssl/ssl/s2_clnt.c
crypto/openssl/ssl/s2_lib.c
crypto/openssl/ssl/s3_both.c
crypto/openssl/ssl/s3_cbc.c
crypto/openssl/ssl/s3_clnt.c
crypto/openssl/ssl/s3_enc.c
crypto/openssl/ssl/s3_lib.c
crypto/openssl/ssl/s3_pkt.c
crypto/openssl/ssl/s3_srvr.c
crypto/openssl/ssl/srtp.h
crypto/openssl/ssl/ssl.h
crypto/openssl/ssl/ssl3.h
crypto/openssl/ssl/ssl_algs.c
crypto/openssl/ssl/ssl_cert.c
crypto/openssl/ssl/ssl_ciph.c
crypto/openssl/ssl/ssl_conf.c [new file with mode: 0644]
crypto/openssl/ssl/ssl_err.c
crypto/openssl/ssl/ssl_lib.c
crypto/openssl/ssl/ssl_locl.h
crypto/openssl/ssl/ssl_rsa.c
crypto/openssl/ssl/ssl_sess.c
crypto/openssl/ssl/ssl_txt.c
crypto/openssl/ssl/t1_clnt.c
crypto/openssl/ssl/t1_enc.c
crypto/openssl/ssl/t1_ext.c [new file with mode: 0644]
crypto/openssl/ssl/t1_lib.c
crypto/openssl/ssl/t1_meth.c
crypto/openssl/ssl/t1_srvr.c
crypto/openssl/ssl/t1_trce.c [new file with mode: 0644]
crypto/openssl/ssl/tls1.h

index 1c7a5ed..4a55765 100644 (file)
@@ -2,7 +2,7 @@
  OpenSSL CHANGES
  _______________
 
- Changes between 1.0.1s and 1.0.1t [3 May 2016]
+ Changes between 1.0.2g and 1.0.2h [3 May 2016]
 
   *) Prevent padding oracle in AES-NI CBC MAC check
 
@@ -99,7 +99,7 @@
      methods are enabled and ssl2 is disabled the methods return NULL.
      [Kurt Roeckx]
 
- Changes between 1.0.1r and 1.0.1s [1 Mar 2016]
+ Changes between 1.0.2f and 1.0.2g [1 Mar 2016]
 
   * Disable weak ciphers in SSLv3 and up in default builds of OpenSSL.
     Builds that are not configured with "enable-weak-ssl-ciphers" will not
      apps to use 2048 bits by default.
      [Emilia Käsper]
 
- Changes between 1.0.1q and 1.0.1r [28 Jan 2016]
-
-  *) Protection for DH small subgroup attacks
-
-     As a precautionary measure the SSL_OP_SINGLE_DH_USE option has been
-     switched on by default and cannot be disabled. This could have some
-     performance impact.
+ Changes between 1.0.2e and 1.0.2f [28 Jan 2016]
+
+  *) DH small subgroups
+
+     Historically OpenSSL only ever generated DH parameters based on "safe"
+     primes. More recently (in version 1.0.2) support was provided for
+     generating X9.42 style parameter files such as those required for RFC 5114
+     support. The primes used in such files may not be "safe". Where an
+     application is using DH configured with parameters based on primes that are
+     not "safe" then an attacker could use this fact to find a peer's private
+     DH exponent. This attack requires that the attacker complete multiple
+     handshakes in which the peer uses the same private DH exponent. For example
+     this could be used to discover a TLS server's private DH exponent if it's
+     reusing the private DH exponent or it's using a static DH ciphersuite.
+
+     OpenSSL provides the option SSL_OP_SINGLE_DH_USE for ephemeral DH (DHE) in
+     TLS. It is not on by default. If the option is not set then the server
+     reuses the same private DH exponent for the life of the server process and
+     would be vulnerable to this attack. It is believed that many popular
+     applications do set this option and would therefore not be at risk.
+
+     The fix for this issue adds an additional check where a "q" parameter is
+     available (as is the case in X9.42 based parameters). This detects the
+     only known attack, and is the only possible defense for static DH
+     ciphersuites. This could have some performance impact.
+
+     Additionally the SSL_OP_SINGLE_DH_USE option has been switched on by
+     default and cannot be disabled. This could have some performance impact.
+
+     This issue was reported to OpenSSL by Antonio Sanso (Adobe).
+     (CVE-2016-0701)
      [Matt Caswell]
 
   *) SSLv2 doesn't block disabled ciphers
   *) Reject DH handshakes with parameters shorter than 1024 bits.
      [Kurt Roeckx]
 
- Changes between 1.0.1p and 1.0.1q [3 Dec 2015]
+ Changes between 1.0.2d and 1.0.2e [3 Dec 2015]
+
+  *) BN_mod_exp may produce incorrect results on x86_64
+
+     There is a carry propagating bug in the x86_64 Montgomery squaring
+     procedure. No EC algorithms are affected. Analysis suggests that attacks
+     against RSA and DSA as a result of this defect would be very difficult to
+     perform and are not believed likely. Attacks against DH are considered just
+     feasible (although very difficult) because most of the work necessary to
+     deduce information about a private key may be performed offline. The amount
+     of resources required for such an attack would be very significant and
+     likely only accessible to a limited number of attackers. An attacker would
+     additionally need online access to an unpatched system using the target
+     private key in a scenario with persistent DH parameters and a private
+     key that is shared between multiple clients. For example this can occur by
+     default in OpenSSL DHE based SSL/TLS ciphersuites.
+
+     This issue was reported to OpenSSL by Hanno Böck.
+     (CVE-2015-3193)
+     [Andy Polyakov]
 
   *) Certificate verify crash with missing PSS parameter
 
      use a random seed, as already documented.
      [Rich Salz and Ismo Puustinen <ismo.puustinen@intel.com>]
 
- Changes between 1.0.1o and 1.0.1p [9 Jul 2015]
+ Changes between 1.0.2c and 1.0.2d [9 Jul 2015]
 
   *) Alternate chains certificate forgery
 
      (CVE-2015-3196)
      [Stephen Henson]
 
- Changes between 1.0.1n and 1.0.1o [12 Jun 2015]
+ Changes between 1.0.2b and 1.0.2c [12 Jun 2015]
+
   *) Fix HMAC ABI incompatibility. The previous version introduced an ABI
      incompatibility in the handling of HMAC. The previous ABI has now been
      restored.
 
- Changes between 1.0.1m and 1.0.1n [11 Jun 2015]
+ Changes between 1.0.2a and 1.0.2b [11 Jun 2015]
 
   *) Malformed ECParameters causes infinite loop
 
      (CVE-2015-1791)
      [Matt Caswell]
 
+  *) Removed support for the two export grade static DH ciphersuites
+     EXP-DH-RSA-DES-CBC-SHA and EXP-DH-DSS-DES-CBC-SHA. These two ciphersuites
+     were newly added (along with a number of other static DH ciphersuites) to
+     1.0.2. However the two export ones have *never* worked since they were
+     introduced. It seems strange in any case to be adding new export
+     ciphersuites, and given "logjam" it also does not seem correct to fix them.
+     [Matt Caswell]
+
+  *) Only support 256-bit or stronger elliptic curves with the
+     'ecdh_auto' setting (server) or by default (client). Of supported
+     curves, prefer P-256 (both).
+     [Emilia Kasper]
+
   *) Reject DH handshakes with parameters shorter than 768 bits.
      [Kurt Roeckx and Emilia Kasper]
 
-  *) dhparam: generate 2048-bit parameters by default.
-     [Kurt Roeckx and Emilia Kasper]
+ Changes between 1.0.2 and 1.0.2a [19 Mar 2015]
+
+  *) ClientHello sigalgs DoS fix
+
+     If a client connects to an OpenSSL 1.0.2 server and renegotiates with an
+     invalid signature algorithms extension a NULL pointer dereference will
+     occur. This can be exploited in a DoS attack against the server.
+
+     This issue was was reported to OpenSSL by David Ramos of Stanford
+     University.
+     (CVE-2015-0291)
+     [Stephen Henson and Matt Caswell]
 
- Changes between 1.0.1l and 1.0.1m [19 Mar 2015]
+  *) Multiblock corrupted pointer fix
+
+     OpenSSL 1.0.2 introduced the "multiblock" performance improvement. This
+     feature only applies on 64 bit x86 architecture platforms that support AES
+     NI instructions. A defect in the implementation of "multiblock" can cause
+     OpenSSL's internal write buffer to become incorrectly set to NULL when
+     using non-blocking IO. Typically, when the user application is using a
+     socket BIO for writing, this will only result in a failed connection.
+     However if some other BIO is used then it is likely that a segmentation
+     fault will be triggered, thus enabling a potential DoS attack.
+
+     This issue was reported to OpenSSL by Daniel Danner and Rainer Mueller.
+     (CVE-2015-0290)
+     [Matt Caswell]
+
+  *) Segmentation fault in DTLSv1_listen fix
+
+     The DTLSv1_listen function is intended to be stateless and processes the
+     initial ClientHello from many peers. It is common for user code to loop
+     over the call to DTLSv1_listen until a valid ClientHello is received with
+     an associated cookie. A defect in the implementation of DTLSv1_listen means
+     that state is preserved in the SSL object from one invocation to the next
+     that can lead to a segmentation fault. Errors processing the initial
+     ClientHello can trigger this scenario. An example of such an error could be
+     that a DTLS1.0 only client is attempting to connect to a DTLS1.2 only
+     server.
+
+     This issue was reported to OpenSSL by Per Allansson.
+     (CVE-2015-0207)
+     [Matt Caswell]
 
   *) Segmentation fault in ASN1_TYPE_cmp fix
 
      (CVE-2015-0286)
      [Stephen Henson]
 
+  *) Segmentation fault for invalid PSS parameters fix
+
+     The signature verification routines will crash with a NULL pointer
+     dereference if presented with an ASN.1 signature using the RSA PSS
+     algorithm and invalid parameters. Since these routines are used to verify
+     certificate signature algorithms this can be used to crash any
+     certificate verification operation and exploited in a DoS attack. Any
+     application which performs certificate verification is vulnerable including
+     OpenSSL clients and servers which enable client authentication.
+
+     This issue was was reported to OpenSSL by Brian Carpenter.
+     (CVE-2015-0208)
+     [Stephen Henson]
+
   *) ASN.1 structure reuse memory corruption fix
 
      Reusing a structure in ASN.1 parsing may allow an attacker to cause
      (CVE-2015-0293)
      [Emilia Käsper]
 
+  *) Empty CKE with client auth and DHE fix
+
+     If client auth is used then a server can seg fault in the event of a DHE
+     ciphersuite being selected and a zero length ClientKeyExchange message
+     being sent by the client. This could be exploited in a DoS attack.
+     (CVE-2015-1787)
+     [Matt Caswell]
+
+  *) Handshake with unseeded PRNG fix
+
+     Under certain conditions an OpenSSL 1.0.2 client can complete a handshake
+     with an unseeded PRNG. The conditions are:
+     - The client is on a platform where the PRNG has not been seeded
+     automatically, and the user has not seeded manually
+     - A protocol specific client method version has been used (i.e. not
+     SSL_client_methodv23)
+     - A ciphersuite is used that does not require additional random data from
+     the PRNG beyond the initial ClientHello client random (e.g. PSK-RC4-SHA).
+
+     If the handshake succeeds then the client random that has been used will
+     have been generated from a PRNG with insufficient entropy and therefore the
+     output may be predictable.
+
+     For example using the following command with an unseeded openssl will
+     succeed on an unpatched platform:
+
+     openssl s_client -psk 1a2b3c4d -tls1_2 -cipher PSK-RC4-SHA
+     (CVE-2015-0285)
+     [Matt Caswell]
+
   *) Use After Free following d2i_ECPrivatekey error fix
 
      A malformed EC private key file consumed via the d2i_ECPrivateKey function
   *) Removed the export ciphers from the DEFAULT ciphers
      [Kurt Roeckx]
 
+ Changes between 1.0.1l and 1.0.2 [22 Jan 2015]
+
+  *) Change RSA and DH/DSA key generation apps to generate 2048-bit
+     keys by default.
+     [Kurt Roeckx]
+
+  *) Facilitate "universal" ARM builds targeting range of ARM ISAs, e.g.
+     ARMv5 through ARMv8, as opposite to "locking" it to single one.
+     So far those who have to target multiple plaforms would compromise
+     and argue that binary targeting say ARMv5 would still execute on
+     ARMv8. "Universal" build resolves this compromise by providing
+     near-optimal performance even on newer platforms.
+     [Andy Polyakov]
+
+  *) Accelerated NIST P-256 elliptic curve implementation for x86_64
+     (other platforms pending).
+     [Shay Gueron & Vlad Krasnov (Intel Corp), Andy Polyakov]
+
+  *) Add support for the SignedCertificateTimestampList certificate and
+     OCSP response extensions from RFC6962.
+     [Rob Stradling]
+
+  *) Fix ec_GFp_simple_points_make_affine (thus, EC_POINTs_mul etc.)
+     for corner cases. (Certain input points at infinity could lead to
+     bogus results, with non-infinity inputs mapped to infinity too.)
+     [Bodo Moeller]
+
+  *) Initial support for PowerISA 2.0.7, first implemented in POWER8.
+     This covers AES, SHA256/512 and GHASH. "Initial" means that most
+     common cases are optimized and there still is room for further
+     improvements. Vector Permutation AES for Altivec is also added.
+     [Andy Polyakov]
+
+  *) Add support for little-endian ppc64 Linux target.
+     [Marcelo Cerri (IBM)]
+
+  *) Initial support for AMRv8 ISA crypto extensions. This covers AES,
+     SHA1, SHA256 and GHASH. "Initial" means that most common cases
+     are optimized and there still is room for further improvements.
+     Both 32- and 64-bit modes are supported.
+     [Andy Polyakov, Ard Biesheuvel (Linaro)]
+
+  *) Improved ARMv7 NEON support.
+     [Andy Polyakov]
+
+  *) Support for SPARC Architecture 2011 crypto extensions, first
+     implemented in SPARC T4. This covers AES, DES, Camellia, SHA1,
+     SHA256/512, MD5, GHASH and modular exponentiation.
+     [Andy Polyakov, David Miller]
+
+  *) Accelerated modular exponentiation for Intel processors, a.k.a.
+     RSAZ.
+     [Shay Gueron & Vlad Krasnov (Intel Corp)]
+
+  *) Support for new and upcoming Intel processors, including AVX2,
+     BMI and SHA ISA extensions. This includes additional "stitched"
+     implementations, AESNI-SHA256 and GCM, and multi-buffer support
+     for TLS encrypt.
+
+     This work was sponsored by Intel Corp.
+     [Andy Polyakov]
+
+  *) Support for DTLS 1.2. This adds two sets of DTLS methods: DTLS_*_method()
+     supports both DTLS 1.2 and 1.0 and should use whatever version the peer
+     supports and DTLSv1_2_*_method() which supports DTLS 1.2 only.
+     [Steve Henson]
+
+  *) Use algorithm specific chains in SSL_CTX_use_certificate_chain_file():
+     this fixes a limiation in previous versions of OpenSSL.
+     [Steve Henson]
+
+  *) Extended RSA OAEP support via EVP_PKEY API. Options to specify digest,
+     MGF1 digest and OAEP label.
+     [Steve Henson]
+
+  *) Add EVP support for key wrapping algorithms, to avoid problems with
+     existing code the flag EVP_CIPHER_CTX_WRAP_ALLOW has to be set in
+     the EVP_CIPHER_CTX or an error is returned. Add AES and DES3 wrap
+     algorithms and include tests cases.
+     [Steve Henson]
+
+  *) Add functions to allocate and set the fields of an ECDSA_METHOD
+     structure.
+     [Douglas E. Engert, Steve Henson]
+
+  *) New functions OPENSSL_gmtime_diff and ASN1_TIME_diff to find the
+     difference in days and seconds between two tm or ASN1_TIME structures.
+     [Steve Henson]
+
+  *) Add -rev test option to s_server to just reverse order of characters
+     received by client and send back to server. Also prints an abbreviated
+     summary of the connection parameters.
+     [Steve Henson]
+
+  *) New option -brief for s_client and s_server to print out a brief summary
+     of connection parameters.
+     [Steve Henson]
+
+  *) Add callbacks for arbitrary TLS extensions.
+     [Trevor Perrin <trevp@trevp.net> and Ben Laurie]
+
+  *) New option -crl_download in several openssl utilities to download CRLs
+     from CRLDP extension in certificates.
+     [Steve Henson]
+
+  *) New options -CRL and -CRLform for s_client and s_server for CRLs.
+     [Steve Henson]
+
+  *) New function X509_CRL_diff to generate a delta CRL from the difference
+     of two full CRLs. Add support to "crl" utility.
+     [Steve Henson]
+
+  *) New functions to set lookup_crls function and to retrieve
+     X509_STORE from X509_STORE_CTX.
+     [Steve Henson]
+
+  *) Print out deprecated issuer and subject unique ID fields in
+     certificates.
+     [Steve Henson]
+
+  *) Extend OCSP I/O functions so they can be used for simple general purpose
+     HTTP as well as OCSP. New wrapper function which can be used to download
+     CRLs using the OCSP API.
+     [Steve Henson]
+
+  *) Delegate command line handling in s_client/s_server to SSL_CONF APIs.
+     [Steve Henson]
+
+  *) SSL_CONF* functions. These provide a common framework for application
+     configuration using configuration files or command lines.
+     [Steve Henson]
+
+  *) SSL/TLS tracing code. This parses out SSL/TLS records using the
+     message callback and prints the results. Needs compile time option
+     "enable-ssl-trace". New options to s_client and s_server to enable
+     tracing.
+     [Steve Henson]
+
+  *) New ctrl and macro to retrieve supported points extensions.
+     Print out extension in s_server and s_client.
+     [Steve Henson]
+
+  *) New functions to retrieve certificate signature and signature
+     OID NID.
+     [Steve Henson]
+
+  *) Add functions to retrieve and manipulate the raw cipherlist sent by a
+     client to OpenSSL.
+     [Steve Henson]
+
+  *) New Suite B modes for TLS code. These use and enforce the requirements
+     of RFC6460: restrict ciphersuites, only permit Suite B algorithms and
+     only use Suite B curves. The Suite B modes can be set by using the
+     strings "SUITEB128", "SUITEB192" or "SUITEB128ONLY" for the cipherstring.
+     [Steve Henson]
+
+  *) New chain verification flags for Suite B levels of security. Check
+     algorithms are acceptable when flags are set in X509_verify_cert.
+     [Steve Henson]
+
+  *) Make tls1_check_chain return a set of flags indicating checks passed
+     by a certificate chain. Add additional tests to handle client
+     certificates: checks for matching certificate type and issuer name
+     comparison.
+     [Steve Henson]
+
+  *) If an attempt is made to use a signature algorithm not in the peer
+     preference list abort the handshake. If client has no suitable
+     signature algorithms in response to a certificate request do not
+     use the certificate.
+     [Steve Henson]
+
+  *) If server EC tmp key is not in client preference list abort handshake.
+     [Steve Henson]
+
+  *) Add support for certificate stores in CERT structure. This makes it
+     possible to have different stores per SSL structure or one store in
+     the parent SSL_CTX. Include distint stores for certificate chain
+     verification and chain building. New ctrl SSL_CTRL_BUILD_CERT_CHAIN
+     to build and store a certificate chain in CERT structure: returing
+     an error if the chain cannot be built: this will allow applications
+     to test if a chain is correctly configured.
+
+     Note: if the CERT based stores are not set then the parent SSL_CTX
+     store is used to retain compatibility with existing behaviour.
+
+     [Steve Henson]
+
+  *) New function ssl_set_client_disabled to set a ciphersuite disabled
+     mask based on the current session, check mask when sending client
+     hello and checking the requested ciphersuite.
+     [Steve Henson]
+
+  *) New ctrls to retrieve and set certificate types in a certificate
+     request message. Print out received values in s_client. If certificate
+     types is not set with custom values set sensible values based on
+     supported signature algorithms.
+     [Steve Henson]
+
+  *) Support for distinct client and server supported signature algorithms.
+     [Steve Henson]
+
+  *) Add certificate callback. If set this is called whenever a certificate
+     is required by client or server. An application can decide which
+     certificate chain to present based on arbitrary criteria: for example
+     supported signature algorithms. Add very simple example to s_server.
+     This fixes many of the problems and restrictions of the existing client
+     certificate callback: for example you can now clear an existing
+     certificate and specify the whole chain.
+     [Steve Henson]
+
+  *) Add new "valid_flags" field to CERT_PKEY structure which determines what
+     the certificate can be used for (if anything). Set valid_flags field 
+     in new tls1_check_chain function. Simplify ssl_set_cert_masks which used
+     to have similar checks in it.
+
+     Add new "cert_flags" field to CERT structure and include a "strict mode".
+     This enforces some TLS certificate requirements (such as only permitting
+     certificate signature algorithms contained in the supported algorithms
+     extension) which some implementations ignore: this option should be used
+     with caution as it could cause interoperability issues.
+     [Steve Henson]
+
+  *) Update and tidy signature algorithm extension processing. Work out
+     shared signature algorithms based on preferences and peer algorithms
+     and print them out in s_client and s_server. Abort handshake if no
+     shared signature algorithms.
+     [Steve Henson]
+
+  *) Add new functions to allow customised supported signature algorithms
+     for SSL and SSL_CTX structures. Add options to s_client and s_server
+     to support them.
+     [Steve Henson]
+
+  *) New function SSL_certs_clear() to delete all references to certificates
+     from an SSL structure. Before this once a certificate had been added
+     it couldn't be removed.
+     [Steve Henson]
+
+  *) Integrate hostname, email address and IP address checking with certificate
+     verification. New verify options supporting checking in opensl utility.
+     [Steve Henson]
+
+  *) Fixes and wildcard matching support to hostname and email checking
+     functions. Add manual page.
+     [Florian Weimer (Red Hat Product Security Team)]
+
+  *) New functions to check a hostname email or IP address against a
+     certificate. Add options x509 utility to print results of checks against
+     a certificate.
+     [Steve Henson]
+
+  *) Fix OCSP checking.
+     [Rob Stradling <rob.stradling@comodo.com> and Ben Laurie]
+
+  *) Initial experimental support for explicitly trusted non-root CAs. 
+     OpenSSL still tries to build a complete chain to a root but if an
+     intermediate CA has a trust setting included that is used. The first
+     setting is used: whether to trust (e.g., -addtrust option to the x509
+     utility) or reject.
+     [Steve Henson]
+
+  *) Add -trusted_first option which attempts to find certificates in the
+     trusted store even if an untrusted chain is also supplied.
+     [Steve Henson]
+
+  *) MIPS assembly pack updates: support for MIPS32r2 and SmartMIPS ASE,
+     platform support for Linux and Android.
+     [Andy Polyakov]
+
+  *) Support for linux-x32, ILP32 environment in x86_64 framework.
+     [Andy Polyakov]
+
+  *) Experimental multi-implementation support for FIPS capable OpenSSL.
+     When in FIPS mode the approved implementations are used as normal,
+     when not in FIPS mode the internal unapproved versions are used instead.
+     This means that the FIPS capable OpenSSL isn't forced to use the
+     (often lower perfomance) FIPS implementations outside FIPS mode.
+     [Steve Henson]
+
+  *) Transparently support X9.42 DH parameters when calling
+     PEM_read_bio_DHparameters. This means existing applications can handle
+     the new parameter format automatically.
+     [Steve Henson]
+
+  *) Initial experimental support for X9.42 DH parameter format: mainly
+     to support use of 'q' parameter for RFC5114 parameters.
+     [Steve Henson]
+
+  *) Add DH parameters from RFC5114 including test data to dhtest.
+     [Steve Henson]
+
+  *) Support for automatic EC temporary key parameter selection. If enabled
+     the most preferred EC parameters are automatically used instead of
+     hardcoded fixed parameters. Now a server just has to call:
+     SSL_CTX_set_ecdh_auto(ctx, 1) and the server will automatically
+     support ECDH and use the most appropriate parameters.
+     [Steve Henson]
+
+  *) Enhance and tidy EC curve and point format TLS extension code. Use
+     static structures instead of allocation if default values are used.
+     New ctrls to set curves we wish to support and to retrieve shared curves.
+     Print out shared curves in s_server. New options to s_server and s_client
+     to set list of supported curves.
+     [Steve Henson]
+
+  *) New ctrls to retrieve supported signature algorithms and 
+     supported curve values as an array of NIDs. Extend openssl utility
+     to print out received values.
+     [Steve Henson]
+
+  *) Add new APIs EC_curve_nist2nid and EC_curve_nid2nist which convert
+     between NIDs and the more common NIST names such as "P-256". Enhance
+     ecparam utility and ECC method to recognise the NIST names for curves.
+     [Steve Henson]
+
+  *) Enhance SSL/TLS certificate chain handling to support different
+     chains for each certificate instead of one chain in the parent SSL_CTX.
+     [Steve Henson]
+
+  *) Support for fixed DH ciphersuite client authentication: where both
+     server and client use DH certificates with common parameters.
+     [Steve Henson]
+
+  *) Support for fixed DH ciphersuites: those requiring DH server
+     certificates.
+     [Steve Henson]
+
+  *) New function i2d_re_X509_tbs for re-encoding the TBS portion of
+     the certificate.
+     Note: Related 1.0.2-beta specific macros X509_get_cert_info,
+     X509_CINF_set_modified, X509_CINF_get_issuer, X509_CINF_get_extensions and
+     X509_CINF_get_signature were reverted post internal team review.
+
  Changes between 1.0.1k and 1.0.1l [15 Jan 2015]
 
   *) Build fixes for the Windows and OpenVMS platforms
      [mancha <mancha1@zoho.com>]
 
   *) Fix eckey_priv_encode so it immediately returns an error upon a failure
-     in i2d_ECPrivateKey.
+     in i2d_ECPrivateKey.  Thanks to Ted Unangst for feedback on this issue.
      [mancha <mancha1@zoho.com>]
 
   *) Fix some double frees. These are not thought to be exploitable.
index 0fb2cc3..6c85116 100644 (file)
@@ -5,7 +5,7 @@
   This file gives a brief overview of the major changes between each OpenSSL
   release. For more details please read the CHANGES file.
 
-  Major changes between OpenSSL 1.0.1s and OpenSSL 1.0.1t [3 May 2016]
+  Major changes between OpenSSL 1.0.2g and OpenSSL 1.0.2h [3 May 2016]
 
       o Prevent padding oracle in AES-NI CBC MAC check (CVE-2016-2107)
       o Fix EVP_EncodeUpdate overflow (CVE-2016-2105)
@@ -18,7 +18,7 @@
         the default.
       o Only remove the SSLv2 methods with the no-ssl2-method option.
 
-  Major changes between OpenSSL 1.0.1r and OpenSSL 1.0.1s [1 Mar 2016]
+  Major changes between OpenSSL 1.0.2f and OpenSSL 1.0.2g [1 Mar 2016]
 
       o Disable weak ciphers in SSLv3 and up in default builds of OpenSSL.
       o Disable SSLv2 default build, default negotiation and weak ciphers
       o Fix memory issues in BIO_*printf functions (CVE-2016-0799)
       o Fix side channel attack on modular exponentiation (CVE-2016-0702)
 
-  Major changes between OpenSSL 1.0.1q and OpenSSL 1.0.1r [28 Jan 2016]
+  Major changes between OpenSSL 1.0.2e and OpenSSL 1.0.2f [28 Jan 2016]
 
-      o Protection for DH small subgroup attacks
+      o DH small subgroups (CVE-2016-0701)
       o SSLv2 doesn't block disabled ciphers (CVE-2015-3197)
 
-  Major changes between OpenSSL 1.0.1p and OpenSSL 1.0.1q [3 Dec 2015]
+  Major changes between OpenSSL 1.0.2d and OpenSSL 1.0.2e [3 Dec 2015]
 
+      o BN_mod_exp may produce incorrect results on x86_64 (CVE-2015-3193)
       o Certificate verify crash with missing PSS parameter (CVE-2015-3194)
       o X509_ATTRIBUTE memory leak (CVE-2015-3195)
       o Rewrite EVP_DecodeUpdate (base64 decoding) to fix several bugs
       o In DSA_generate_parameters_ex, if the provided seed is too short,
         return an error
 
-  Major changes between OpenSSL 1.0.1o and OpenSSL 1.0.1p [9 Jul 2015]
+  Major changes between OpenSSL 1.0.2c and OpenSSL 1.0.2d [9 Jul 2015]
 
       o Alternate chains certificate forgery (CVE-2015-1793)
       o Race condition handling PSK identify hint (CVE-2015-3196)
 
-  Major changes between OpenSSL 1.0.1n and OpenSSL 1.0.1o [12 Jun 2015]
+  Major changes between OpenSSL 1.0.2b and OpenSSL 1.0.2c [12 Jun 2015]
 
       o Fix HMAC ABI incompatibility
 
-  Major changes between OpenSSL 1.0.1m and OpenSSL 1.0.1n [11 Jun 2015]
+  Major changes between OpenSSL 1.0.2a and OpenSSL 1.0.2b [11 Jun 2015]
 
       o Malformed ECParameters causes infinite loop (CVE-2015-1788)
       o Exploitable out-of-bounds read in X509_cmp_time (CVE-2015-1789)
       o CMS verify infinite loop with unknown hash function (CVE-2015-1792)
       o Race condition handling NewSessionTicket (CVE-2015-1791)
 
-  Major changes between OpenSSL 1.0.1l and OpenSSL 1.0.1m [19 Mar 2015]
+  Major changes between OpenSSL 1.0.2 and OpenSSL 1.0.2a [19 Mar 2015]
 
+      o OpenSSL 1.0.2 ClientHello sigalgs DoS fix (CVE-2015-0291)
+      o Multiblock corrupted pointer fix (CVE-2015-0290)
+      o Segmentation fault in DTLSv1_listen fix (CVE-2015-0207)
       o Segmentation fault in ASN1_TYPE_cmp fix (CVE-2015-0286)
+      o Segmentation fault for invalid PSS parameters fix (CVE-2015-0208)
       o ASN.1 structure reuse memory corruption fix (CVE-2015-0287)
       o PKCS7 NULL pointer dereferences fix (CVE-2015-0289)
       o DoS via reachable assert in SSLv2 servers fix (CVE-2015-0293)
+      o Empty CKE with client auth and DHE fix (CVE-2015-1787)
+      o Handshake with unseeded PRNG fix (CVE-2015-0285)
       o Use After Free following d2i_ECPrivatekey error fix (CVE-2015-0209)
       o X509_to_X509_REQ NULL pointer deref fix (CVE-2015-0288)
       o Removed the export ciphers from the DEFAULT ciphers
 
+  Major changes between OpenSSL 1.0.1l and OpenSSL 1.0.2 [22 Jan 2015]:
+
+      o Suite B support for TLS 1.2 and DTLS 1.2
+      o Support for DTLS 1.2
+      o TLS automatic EC curve selection.
+      o API to set TLS supported signature algorithms and curves
+      o SSL_CONF configuration API.
+      o TLS Brainpool support.
+      o ALPN support.
+      o CMS support for RSA-PSS, RSA-OAEP, ECDH and X9.42 DH.
+
   Major changes between OpenSSL 1.0.1k and OpenSSL 1.0.1l [15 Jan 2015]
 
       o Build fixes for the Windows and OpenVMS platforms
index 9395f2b..b880eec 100644 (file)
@@ -1,5 +1,5 @@
 
- OpenSSL 1.0.1t 3 May 2016
+ OpenSSL 1.0.2h 3 May 2016
 
  Copyright (c) 1998-2015 The OpenSSL Project
  Copyright (c) 1995-1998 Eric A. Young, Tim J. Hudson
index ac11e94..6f657fe 100644 (file)
@@ -1,6 +1,8 @@
 ACKNOWLEDGMENTS
 CHANGES.SSLeay
 Configure
+GitConfigure
+GitMake
 INSTALL
 INSTALL.DJGPP
 INSTALL.MacOS
@@ -71,6 +73,7 @@ crypto/LPdir_wince.c
 crypto/Makefile
 crypto/aes/Makefile
 crypto/aes/aes_x86core.c
+crypto/aes/asm/aes-586.pl
 crypto/aes/asm/aes-armv4.pl
 crypto/aes/asm/aes-ia64.S
 crypto/aes/asm/aes-mips.pl
@@ -78,7 +81,15 @@ crypto/aes/asm/aes-parisc.pl
 crypto/aes/asm/aes-ppc.pl
 crypto/aes/asm/aes-s390x.pl
 crypto/aes/asm/aes-sparcv9.pl
+crypto/aes/asm/aesni-x86.pl
+crypto/aes/asm/aesp8-ppc.pl
+crypto/aes/asm/aest4-sparcv9.pl
+crypto/aes/asm/aesv8-armx.pl
+crypto/aes/asm/bsaes-armv7.pl
+crypto/aes/asm/vpaes-ppc.pl
+crypto/aes/asm/vpaes-x86.pl
 crypto/alphacpuid.pl
+crypto/arm64cpuid.S
 crypto/arm_arch.h
 crypto/armcap.c
 crypto/armv4cpuid.S
@@ -86,8 +97,7 @@ crypto/asn1/Makefile
 crypto/asn1/charmap.pl
 crypto/bf/INSTALL
 crypto/bf/Makefile
-crypto/bf/asm/bf-686.pl
-crypto/bf/asm/readme
+crypto/bf/asm/
 crypto/bf/bf_cbc.c
 crypto/bf/bf_opts.c
 crypto/bf/bfs.cpp
@@ -100,11 +110,14 @@ crypto/bn/asm/README
 crypto/bn/asm/alpha-mont.pl
 crypto/bn/asm/armv4-gf2m.pl
 crypto/bn/asm/armv4-mont.pl
+crypto/bn/asm/bn-586.pl
+crypto/bn/asm/co-586.pl
 crypto/bn/asm/ia64-mont.pl
 crypto/bn/asm/ia64.S
 crypto/bn/asm/mips-mont.pl
 crypto/bn/asm/mips.pl
 crypto/bn/asm/mips3-mont.pl
+crypto/bn/asm/mips3.s
 crypto/bn/asm/pa-risc2.s
 crypto/bn/asm/pa-risc2W.s
 crypto/bn/asm/parisc-mont.pl
@@ -114,11 +127,14 @@ crypto/bn/asm/ppc64-mont.pl
 crypto/bn/asm/s390x-gf2m.pl
 crypto/bn/asm/s390x-mont.pl
 crypto/bn/asm/s390x.S
+crypto/bn/asm/sparct4-mont.pl
 crypto/bn/asm/sparcv8.S
 crypto/bn/asm/sparcv8plus.S
+crypto/bn/asm/sparcv9-gf2m.pl
 crypto/bn/asm/sparcv9-mont.pl
 crypto/bn/asm/sparcv9a-mont.pl
 crypto/bn/asm/via-mont.pl
+crypto/bn/asm/vis3-mont.pl
 crypto/bn/asm/vms.mar
 crypto/bn/asm/x86/
 crypto/bn/asm/x86-gf2m.pl
@@ -135,6 +151,8 @@ crypto/bn/exptest.c
 crypto/bn/vms-helper.c
 crypto/buffer/Makefile
 crypto/camellia/Makefile
+crypto/camellia/asm/cmll-x86.pl
+crypto/camellia/asm/cmllt4-sparcv9.pl
 crypto/cast/Makefile
 crypto/cast/asm/
 crypto/cast/cast_spd.c
@@ -158,8 +176,7 @@ crypto/des/INSTALL
 crypto/des/Imakefile
 crypto/des/KERBEROS
 crypto/des/Makefile
-crypto/des/asm/des_enc.m4
-crypto/des/asm/readme
+crypto/des/asm/
 crypto/des/des-lib.com
 crypto/des/des.c
 crypto/des/des.pod
@@ -228,7 +245,9 @@ crypto/md4/md4.c
 crypto/md4/md4s.cpp
 crypto/md4/md4test.c
 crypto/md5/Makefile
+crypto/md5/asm/md5-586.pl
 crypto/md5/asm/md5-ia64.S
+crypto/md5/asm/md5-sparcv9.pl
 crypto/md5/md5.c
 crypto/md5/md5s.cpp
 crypto/md5/md5test.c
@@ -241,6 +260,9 @@ crypto/modes/asm/ghash-ia64.pl
 crypto/modes/asm/ghash-parisc.pl
 crypto/modes/asm/ghash-s390x.pl
 crypto/modes/asm/ghash-sparcv9.pl
+crypto/modes/asm/ghash-x86.pl
+crypto/modes/asm/ghashp8-ppc.pl
+crypto/modes/asm/ghashv8-armx.pl
 crypto/o_dir_test.c
 crypto/o_str.c
 crypto/o_str.h
@@ -257,13 +279,18 @@ crypto/opensslconf.h.in
 crypto/pariscid.pl
 crypto/pem/Makefile
 crypto/pem/pkcs7.lis
+crypto/perlasm/cbc.pl
 crypto/perlasm/ppc-xlate.pl
 crypto/perlasm/readme
+crypto/perlasm/sparcv9_modes.pl
+crypto/perlasm/x86asm.pl
+crypto/perlasm/x86gas.pl
 crypto/perlasm/x86masm.pl
 crypto/perlasm/x86nasm.pl
 crypto/pkcs12/Makefile
 crypto/pkcs7/Makefile
 crypto/pkcs7/pk7_enc.c
+crypto/ppc_arch.h
 crypto/ppccap.c
 crypto/ppccpuid.pl
 crypto/pqueue/Makefile
@@ -278,6 +305,7 @@ crypto/rc2/rc2test.c
 crypto/rc2/rrc2.doc
 crypto/rc2/tab.c
 crypto/rc4/Makefile
+crypto/rc4/asm/rc4-586.pl
 crypto/rc4/asm/rc4-ia64.pl
 crypto/rc4/asm/rc4-parisc.pl
 crypto/rc4/asm/rc4-s390x.pl
@@ -288,7 +316,7 @@ crypto/rc4/rc4test.c
 crypto/rc4/rrc4.doc
 crypto/rc5/
 crypto/ripemd/Makefile
-crypto/ripemd/asm/rips.cpp
+crypto/ripemd/asm/
 crypto/ripemd/rmd160.c
 crypto/ripemd/rmdtest.c
 crypto/rsa/Makefile
@@ -298,8 +326,10 @@ crypto/s390xcpuid.S
 crypto/seed/Makefile
 crypto/sha/Makefile
 crypto/sha/asm/README
+crypto/sha/asm/sha1-586.pl
 crypto/sha/asm/sha1-alpha.pl
 crypto/sha/asm/sha1-armv4-large.pl
+crypto/sha/asm/sha1-armv8.pl
 crypto/sha/asm/sha1-ia64.pl
 crypto/sha/asm/sha1-mips.pl
 crypto/sha/asm/sha1-parisc.pl
@@ -308,20 +338,25 @@ crypto/sha/asm/sha1-s390x.pl
 crypto/sha/asm/sha1-sparcv9.pl
 crypto/sha/asm/sha1-sparcv9a.pl
 crypto/sha/asm/sha1-thumb.pl
+crypto/sha/asm/sha256-586.pl
 crypto/sha/asm/sha256-armv4.pl
+crypto/sha/asm/sha512-586.pl
 crypto/sha/asm/sha512-armv4.pl
+crypto/sha/asm/sha512-armv8.pl
 crypto/sha/asm/sha512-ia64.pl
 crypto/sha/asm/sha512-mips.pl
 crypto/sha/asm/sha512-parisc.pl
 crypto/sha/asm/sha512-ppc.pl
 crypto/sha/asm/sha512-s390x.pl
 crypto/sha/asm/sha512-sparcv9.pl
+crypto/sha/asm/sha512p8-ppc.pl
 crypto/sha/sha.c
 crypto/sha/sha1.c
 crypto/sha/sha1test.c
 crypto/sha/sha256t.c
 crypto/sha/sha512t.c
 crypto/sha/shatest.c
+crypto/sparc_arch.h
 crypto/sparccpuid.S
 crypto/sparcv9cap.c
 crypto/srp/Makefile
@@ -343,6 +378,7 @@ crypto/txt_db/Makefile
 crypto/ui/Makefile
 crypto/vms_rms.h
 crypto/whrlpool/Makefile
+crypto/whrlpool/asm/wp-mmx.pl
 crypto/whrlpool/wp_test.c
 crypto/x509/Makefile
 crypto/x509/verify_extra_test.c
@@ -350,6 +386,7 @@ crypto/x509v3/Makefile
 crypto/x509v3/tabtest.c
 crypto/x509v3/v3conf.c
 crypto/x509v3/v3prin.c
+crypto/x86cpuid.pl
 demos/
 doc/
 engines/Makefile
@@ -389,7 +426,7 @@ ssl/install-ssl.com
 ssl/ssl-lib.com
 ssl/ssl_task.c
 ssl/ssltest.c
+ssl/sslv2conftest.c
 test/
-times/
 tools/
 util/
index 1716da8..a3965ec 100644 (file)
@@ -1,4 +1,4 @@
-#!/usr/local/bin/perl5
+#!/usr/bin/perl
 #
 # CA - wrapper around ca to make it easier to use ... basically ca requires
 #      some setup stuff to be done before you can use it and this makes
index 595fc78..7f40bba 100644 (file)
@@ -124,10 +124,7 @@ int app_RAND_load_file(const char *file, BIO *bio_e, int dont_warn)
     char buffer[200];
 
 #ifdef OPENSSL_SYS_WINDOWS
-    BIO_printf(bio_e, "Loading 'screen' into random state -");
-    BIO_flush(bio_e);
     RAND_screen();
-    BIO_printf(bio_e, " done\n");
 #endif
 
     if (file == NULL)
index 8ab4833..b1dd970 100644 (file)
@@ -282,6 +282,8 @@ int str2fmt(char *s)
         return (FORMAT_PKCS12);
     else if ((*s == 'E') || (*s == 'e'))
         return (FORMAT_ENGINE);
+    else if ((*s == 'H') || (*s == 'h'))
+        return FORMAT_HTTP;
     else if ((*s == 'P') || (*s == 'p')) {
         if (s[1] == 'V' || s[1] == 'v')
             return FORMAT_PVK;
@@ -784,12 +786,72 @@ static int load_pkcs12(BIO *err, BIO *in, const char *desc,
     return ret;
 }
 
+int load_cert_crl_http(const char *url, BIO *err,
+                       X509 **pcert, X509_CRL **pcrl)
+{
+    char *host = NULL, *port = NULL, *path = NULL;
+    BIO *bio = NULL;
+    OCSP_REQ_CTX *rctx = NULL;
+    int use_ssl, rv = 0;
+    if (!OCSP_parse_url(url, &host, &port, &path, &use_ssl))
+        goto err;
+    if (use_ssl) {
+        if (err)
+            BIO_puts(err, "https not supported\n");
+        goto err;
+    }
+    bio = BIO_new_connect(host);
+    if (!bio || !BIO_set_conn_port(bio, port))
+        goto err;
+    rctx = OCSP_REQ_CTX_new(bio, 1024);
+    if (!rctx)
+        goto err;
+    if (!OCSP_REQ_CTX_http(rctx, "GET", path))
+        goto err;
+    if (!OCSP_REQ_CTX_add1_header(rctx, "Host", host))
+        goto err;
+    if (pcert) {
+        do {
+            rv = X509_http_nbio(rctx, pcert);
+        }
+        while (rv == -1);
+    } else {
+        do {
+            rv = X509_CRL_http_nbio(rctx, pcrl);
+        } while (rv == -1);
+    }
+
+ err:
+    if (host)
+        OPENSSL_free(host);
+    if (path)
+        OPENSSL_free(path);
+    if (port)
+        OPENSSL_free(port);
+    if (bio)
+        BIO_free_all(bio);
+    if (rctx)
+        OCSP_REQ_CTX_free(rctx);
+    if (rv != 1) {
+        if (bio && err)
+            BIO_printf(bio_err, "Error loading %s from %s\n",
+                       pcert ? "certificate" : "CRL", url);
+        ERR_print_errors(bio_err);
+    }
+    return rv;
+}
+
 X509 *load_cert(BIO *err, const char *file, int format,
                 const char *pass, ENGINE *e, const char *cert_descrip)
 {
     X509 *x = NULL;
     BIO *cert;
 
+    if (format == FORMAT_HTTP) {
+        load_cert_crl_http(file, err, &x, NULL);
+        return x;
+    }
+
     if ((cert = BIO_new(BIO_s_file())) == NULL) {
         ERR_print_errors(err);
         goto end;
@@ -847,6 +909,49 @@ X509 *load_cert(BIO *err, const char *file, int format,
     return (x);
 }
 
+X509_CRL *load_crl(const char *infile, int format)
+{
+    X509_CRL *x = NULL;
+    BIO *in = NULL;
+
+    if (format == FORMAT_HTTP) {
+        load_cert_crl_http(infile, bio_err, NULL, &x);
+        return x;
+    }
+
+    in = BIO_new(BIO_s_file());
+    if (in == NULL) {
+        ERR_print_errors(bio_err);
+        goto end;
+    }
+
+    if (infile == NULL)
+        BIO_set_fp(in, stdin, BIO_NOCLOSE);
+    else {
+        if (BIO_read_filename(in, infile) <= 0) {
+            perror(infile);
+            goto end;
+        }
+    }
+    if (format == FORMAT_ASN1)
+        x = d2i_X509_CRL_bio(in, NULL);
+    else if (format == FORMAT_PEM)
+        x = PEM_read_bio_X509_CRL(in, NULL, NULL, NULL);
+    else {
+        BIO_printf(bio_err, "bad input format specified for input crl\n");
+        goto end;
+    }
+    if (x == NULL) {
+        BIO_printf(bio_err, "unable to load CRL\n");
+        ERR_print_errors(bio_err);
+        goto end;
+    }
+
+ end:
+    BIO_free(in);
+    return (x);
+}
+
 EVP_PKEY *load_key(BIO *err, const char *file, int format, int maybe_stdin,
                    const char *pass, ENGINE *e, const char *key_descrip)
 {
@@ -2160,6 +2265,9 @@ int args_verify(char ***pargs, int *pargc,
     char **oldargs = *pargs;
     char *arg = **pargs, *argn = (*pargs)[1];
     time_t at_time = 0;
+    char *hostname = NULL;
+    char *email = NULL;
+    char *ipasc = NULL;
     if (!strcmp(arg, "-policy")) {
         if (!argn)
             *badarg = 1;
@@ -2213,6 +2321,21 @@ int args_verify(char ***pargs, int *pargc,
             at_time = (time_t)timestamp;
         }
         (*pargs)++;
+    } else if (strcmp(arg, "-verify_hostname") == 0) {
+        if (!argn)
+            *badarg = 1;
+        hostname = argn;
+        (*pargs)++;
+    } else if (strcmp(arg, "-verify_email") == 0) {
+        if (!argn)
+            *badarg = 1;
+        email = argn;
+        (*pargs)++;
+    } else if (strcmp(arg, "-verify_ip") == 0) {
+        if (!argn)
+            *badarg = 1;
+        ipasc = argn;
+        (*pargs)++;
     } else if (!strcmp(arg, "-ignore_critical"))
         flags |= X509_V_FLAG_IGNORE_CRITICAL;
     else if (!strcmp(arg, "-issuer_checks"))
@@ -2239,6 +2362,16 @@ int args_verify(char ***pargs, int *pargc,
         flags |= X509_V_FLAG_NOTIFY_POLICY;
     else if (!strcmp(arg, "-check_ss_sig"))
         flags |= X509_V_FLAG_CHECK_SS_SIGNATURE;
+    else if (!strcmp(arg, "-trusted_first"))
+        flags |= X509_V_FLAG_TRUSTED_FIRST;
+    else if (!strcmp(arg, "-suiteB_128_only"))
+        flags |= X509_V_FLAG_SUITEB_128_LOS_ONLY;
+    else if (!strcmp(arg, "-suiteB_128"))
+        flags |= X509_V_FLAG_SUITEB_128_LOS;
+    else if (!strcmp(arg, "-suiteB_192"))
+        flags |= X509_V_FLAG_SUITEB_192_LOS;
+    else if (!strcmp(arg, "-partial_chain"))
+        flags |= X509_V_FLAG_PARTIAL_CHAIN;
     else if (!strcmp(arg, "-no_alt_chains"))
         flags |= X509_V_FLAG_NO_ALT_CHAINS;
     else
@@ -2270,6 +2403,15 @@ int args_verify(char ***pargs, int *pargc,
     if (at_time)
         X509_VERIFY_PARAM_set_time(*pm, at_time);
 
+    if (hostname && !X509_VERIFY_PARAM_set1_host(*pm, hostname, 0))
+        *badarg = 1;
+
+    if (email && !X509_VERIFY_PARAM_set1_email(*pm, email, 0))
+        *badarg = 1;
+
+    if (ipasc && !X509_VERIFY_PARAM_set1_ip_asc(*pm, ipasc))
+        *badarg = 1;
+
  end:
 
     (*pargs)++;
@@ -2300,7 +2442,11 @@ int bio_to_mem(unsigned char **out, int maxlen, BIO *in)
         else
             len = 1024;
         len = BIO_read(in, tbuf, len);
-        if (len <= 0)
+        if (len < 0) {
+            BIO_free(mem);
+            return -1;
+        }
+        if (len == 0)
             break;
         if (BIO_write(mem, tbuf, len) != len) {
             BIO_free(mem);
@@ -2317,7 +2463,7 @@ int bio_to_mem(unsigned char **out, int maxlen, BIO *in)
     return ret;
 }
 
-int pkey_ctrl_string(EVP_PKEY_CTX *ctx, char *value)
+int pkey_ctrl_string(EVP_PKEY_CTX *ctx, const char *value)
 {
     int rv;
     char *stmp, *vtmp = NULL;
@@ -2553,6 +2699,9 @@ void jpake_client_auth(BIO *out, BIO *conn, const char *secret)
 
     BIO_puts(out, "JPAKE authentication succeeded, setting PSK\n");
 
+    if (psk_key)
+        OPENSSL_free(psk_key);
+
     psk_key = BN_bn2hex(JPAKE_get_shared_key(ctx));
 
     BIO_pop(bconn);
@@ -2582,6 +2731,9 @@ void jpake_server_auth(BIO *out, BIO *conn, const char *secret)
 
     BIO_puts(out, "JPAKE authentication succeeded, setting PSK\n");
 
+    if (psk_key)
+        OPENSSL_free(psk_key);
+
     psk_key = BN_bn2hex(JPAKE_get_shared_key(ctx));
 
     BIO_pop(bconn);
@@ -2592,7 +2744,7 @@ void jpake_server_auth(BIO *out, BIO *conn, const char *secret)
 
 #endif
 
-#if !defined(OPENSSL_NO_TLSEXT) && !defined(OPENSSL_NO_NEXTPROTONEG)
+#ifndef OPENSSL_NO_TLSEXT
 /*-
  * next_protos_parse parses a comma separated list of strings into a string
  * in a format suitable for passing to SSL_CTX_set_next_protos_advertised.
@@ -2631,8 +2783,106 @@ unsigned char *next_protos_parse(unsigned short *outlen, const char *in)
     *outlen = len + 1;
     return out;
 }
-#endif                          /* !OPENSSL_NO_TLSEXT &&
-                                 * !OPENSSL_NO_NEXTPROTONEG */
+#endif                          /* ndef OPENSSL_NO_TLSEXT */
+
+void print_cert_checks(BIO *bio, X509 *x,
+                       const char *checkhost,
+                       const char *checkemail, const char *checkip)
+{
+    if (x == NULL)
+        return;
+    if (checkhost) {
+        BIO_printf(bio, "Hostname %s does%s match certificate\n",
+                   checkhost, X509_check_host(x, checkhost, 0, 0, NULL) == 1
+                   ? "" : " NOT");
+    }
+
+    if (checkemail) {
+        BIO_printf(bio, "Email %s does%s match certificate\n",
+                   checkemail, X509_check_email(x, checkemail, 0,
+                                                0) ? "" : " NOT");
+    }
+
+    if (checkip) {
+        BIO_printf(bio, "IP %s does%s match certificate\n",
+                   checkip, X509_check_ip_asc(x, checkip, 0) ? "" : " NOT");
+    }
+}
+
+/* Get first http URL from a DIST_POINT structure */
+
+static const char *get_dp_url(DIST_POINT *dp)
+{
+    GENERAL_NAMES *gens;
+    GENERAL_NAME *gen;
+    int i, gtype;
+    ASN1_STRING *uri;
+    if (!dp->distpoint || dp->distpoint->type != 0)
+        return NULL;
+    gens = dp->distpoint->name.fullname;
+    for (i = 0; i < sk_GENERAL_NAME_num(gens); i++) {
+        gen = sk_GENERAL_NAME_value(gens, i);
+        uri = GENERAL_NAME_get0_value(gen, &gtype);
+        if (gtype == GEN_URI && ASN1_STRING_length(uri) > 6) {
+            char *uptr = (char *)ASN1_STRING_data(uri);
+            if (!strncmp(uptr, "http://", 7))
+                return uptr;
+        }
+    }
+    return NULL;
+}
+
+/*
+ * Look through a CRLDP structure and attempt to find an http URL to
+ * downloads a CRL from.
+ */
+
+static X509_CRL *load_crl_crldp(STACK_OF(DIST_POINT) *crldp)
+{
+    int i;
+    const char *urlptr = NULL;
+    for (i = 0; i < sk_DIST_POINT_num(crldp); i++) {
+        DIST_POINT *dp = sk_DIST_POINT_value(crldp, i);
+        urlptr = get_dp_url(dp);
+        if (urlptr)
+            return load_crl(urlptr, FORMAT_HTTP);
+    }
+    return NULL;
+}
+
+/*
+ * Example of downloading CRLs from CRLDP: not usable for real world as it
+ * always downloads, doesn't support non-blocking I/O and doesn't cache
+ * anything.
+ */
+
+static STACK_OF(X509_CRL) *crls_http_cb(X509_STORE_CTX *ctx, X509_NAME *nm)
+{
+    X509 *x;
+    STACK_OF(X509_CRL) *crls = NULL;
+    X509_CRL *crl;
+    STACK_OF(DIST_POINT) *crldp;
+    x = X509_STORE_CTX_get_current_cert(ctx);
+    crldp = X509_get_ext_d2i(x, NID_crl_distribution_points, NULL, NULL);
+    crl = load_crl_crldp(crldp);
+    sk_DIST_POINT_pop_free(crldp, DIST_POINT_free);
+    if (!crl)
+        return NULL;
+    crls = sk_X509_CRL_new_null();
+    sk_X509_CRL_push(crls, crl);
+    /* Try to download delta CRL */
+    crldp = X509_get_ext_d2i(x, NID_freshest_crl, NULL, NULL);
+    crl = load_crl_crldp(crldp);
+    sk_DIST_POINT_pop_free(crldp, DIST_POINT_free);
+    if (crl)
+        sk_X509_CRL_push(crls, crl);
+    return crls;
+}
+
+void store_setup_crl_download(X509_STORE *st)
+{
+    X509_STORE_set_lookup_crls_cb(st, crls_http_cb);
+}
 
 /*
  * Platform-specific sections
index 33b293e..19bf5cc 100644 (file)
@@ -205,7 +205,7 @@ extern BIO *bio_err;
 #  endif
 # endif
 
-# ifdef OPENSSL_SYSNAME_WIN32
+# if defined(OPENSSL_SYSNAME_WIN32) || defined(OPENSSL_SYSNAME_WINCE)
 #  define openssl_fdset(a,b) FD_SET((unsigned int)a, b)
 # else
 #  define openssl_fdset(a,b) FD_SET(a, b)
@@ -245,6 +245,9 @@ int app_passwd(BIO *err, char *arg1, char *arg2, char **pass1, char **pass2);
 int add_oid_section(BIO *err, CONF *conf);
 X509 *load_cert(BIO *err, const char *file, int format,
                 const char *pass, ENGINE *e, const char *cert_descrip);
+X509_CRL *load_crl(const char *infile, int format);
+int load_cert_crl_http(const char *url, BIO *err,
+                       X509 **pcert, X509_CRL **pcrl);
 EVP_PKEY *load_key(BIO *err, const char *file, int format, int maybe_stdin,
                    const char *pass, ENGINE *e, const char *key_descrip);
 EVP_PKEY *load_pubkey(BIO *err, const char *file, int format, int maybe_stdin,
@@ -262,8 +265,9 @@ ENGINE *setup_engine(BIO *err, const char *engine, int debug);
 
 # ifndef OPENSSL_NO_OCSP
 OCSP_RESPONSE *process_responder(BIO *err, OCSP_REQUEST *req,
-                                 char *host, char *path, char *port,
-                                 int use_ssl, STACK_OF(CONF_VALUE) *headers,
+                                 const char *host, const char *path,
+                                 const char *port, int use_ssl,
+                                 const STACK_OF(CONF_VALUE) *headers,
                                  int req_timeout);
 # endif
 
@@ -317,7 +321,7 @@ int args_verify(char ***pargs, int *pargc,
                 int *badarg, BIO *err, X509_VERIFY_PARAM **pm);
 void policies_print(BIO *out, X509_STORE_CTX *ctx);
 int bio_to_mem(unsigned char **out, int maxlen, BIO *in);
-int pkey_ctrl_string(EVP_PKEY_CTX *ctx, char *value);
+int pkey_ctrl_string(EVP_PKEY_CTX *ctx, const char *value);
 int init_gen_str(BIO *err, EVP_PKEY_CTX **pctx,
                  const char *algname, ENGINE *e, int do_param);
 int do_X509_sign(BIO *err, X509 *x, EVP_PKEY *pkey, const EVP_MD *md,
@@ -334,10 +338,15 @@ void jpake_client_auth(BIO *out, BIO *conn, const char *secret);
 void jpake_server_auth(BIO *out, BIO *conn, const char *secret);
 # endif
 
-# if !defined(OPENSSL_NO_TLSEXT) && !defined(OPENSSL_NO_NEXTPROTONEG)
+# ifndef OPENSSL_NO_TLSEXT
 unsigned char *next_protos_parse(unsigned short *outlen, const char *in);
-# endif                         /* !OPENSSL_NO_TLSEXT &&
-                                 * !OPENSSL_NO_NEXTPROTONEG */
+# endif                         /* ndef OPENSSL_NO_TLSEXT */
+
+void print_cert_checks(BIO *bio, X509 *x,
+                       const char *checkhost,
+                       const char *checkemail, const char *checkip);
+
+void store_setup_crl_download(X509_STORE *st);
 
 # define FORMAT_UNDEF    0
 # define FORMAT_ASN1     1
@@ -353,6 +362,7 @@ unsigned char *next_protos_parse(unsigned short *outlen, const char *in);
 # define FORMAT_ASN1RSA  10     /* DER RSAPubicKey format */
 # define FORMAT_MSBLOB   11     /* MS Key blob format */
 # define FORMAT_PVK      12     /* MS PVK file format */
+# define FORMAT_HTTP     13     /* Download using HTTP */
 
 # define EXT_COPY_NONE   0
 # define EXT_COPY_ADD    1
index 4d64eb2..0b66095 100644 (file)
@@ -473,6 +473,11 @@ int MAIN(int argc, char **argv)
                 goto bad;
             infile = *(++argv);
             dorevoke = 1;
+        } else if (strcmp(*argv, "-valid") == 0) {
+            if (--argc < 1)
+                goto bad;
+            infile = *(++argv);
+            dorevoke = 2;
         } else if (strcmp(*argv, "-extensions") == 0) {
             if (--argc < 1)
                 goto bad;
@@ -1435,6 +1440,8 @@ int MAIN(int argc, char **argv)
             revcert = load_cert(bio_err, infile, FORMAT_PEM, NULL, e, infile);
             if (revcert == NULL)
                 goto err;
+            if (dorevoke == 2)
+                rev_type = -1;
             j = do_revoke(revcert, db, rev_type, rev_arg);
             if (j <= 0)
                 goto err;
@@ -1962,8 +1969,12 @@ static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509,
 
     if (enddate == NULL)
         X509_time_adj_ex(X509_get_notAfter(ret), days, 0, NULL);
-    else
+    else {
+        int tdays;
         ASN1_TIME_set_string(X509_get_notAfter(ret), enddate);
+        ASN1_TIME_diff(&tdays, NULL, NULL, X509_get_notAfter(ret));
+        days = tdays;
+    }
 
     if (!X509_set_subject_name(ret, subject))
         goto err;
@@ -2403,13 +2414,20 @@ static int do_revoke(X509 *x509, CA_DB *db, int type, char *value)
         }
 
         /* Revoke Certificate */
-        ok = do_revoke(x509, db, type, value);
+        if (type == -1)
+            ok = 1;
+        else
+            ok = do_revoke(x509, db, type, value);
 
         goto err;
 
     } else if (index_name_cmp_noconst(row, rrow)) {
         BIO_printf(bio_err, "ERROR:name does not match %s\n", row[DB_name]);
         goto err;
+    } else if (type == -1) {
+        BIO_printf(bio_err, "ERROR:Already present, serial number %s\n",
+                   row[DB_serial]);
+        goto err;
     } else if (rrow[DB_type][0] == 'R') {
         BIO_printf(bio_err, "ERROR:Already revoked, serial number %s\n",
                    row[DB_serial]);
index f299175..66636d2 100644 (file)
@@ -85,6 +85,9 @@ int MAIN(int argc, char **argv)
 {
     int ret = 1, i;
     int verbose = 0, Verbose = 0;
+#ifndef OPENSSL_NO_SSL_TRACE
+    int stdname = 0;
+#endif
     const char **pp;
     const char *p;
     int badops = 0;
@@ -119,6 +122,10 @@ int MAIN(int argc, char **argv)
             verbose = 1;
         else if (strcmp(*argv, "-V") == 0)
             verbose = Verbose = 1;
+#ifndef OPENSSL_NO_SSL_TRACE
+        else if (strcmp(*argv, "-stdname") == 0)
+            stdname = verbose = 1;
+#endif
 #ifndef OPENSSL_NO_SSL2
         else if (strcmp(*argv, "-ssl2") == 0)
             meth = SSLv2_client_method();
@@ -202,7 +209,14 @@ int MAIN(int argc, char **argv)
                                id1, id2, id3);
                 }
             }
-
+#ifndef OPENSSL_NO_SSL_TRACE
+            if (stdname) {
+                const char *nm = SSL_CIPHER_standard_name(c);
+                if (nm == NULL)
+                    nm = "UNKNOWN";
+                BIO_printf(STDout, "%s - ", nm);
+            }
+#endif
             BIO_puts(STDout, SSL_CIPHER_description(c, buf, sizeof buf));
         }
     }
index d7645c0..6047937 100644 (file)
@@ -75,6 +75,8 @@ static void receipt_request_print(BIO *out, CMS_ContentInfo *cms);
 static CMS_ReceiptRequest *make_receipt_request(STACK_OF(OPENSSL_STRING)
                                                 *rr_to, int rr_allorfirst, STACK_OF(OPENSSL_STRING)
                                                 *rr_from);
+static int cms_set_pkey_param(EVP_PKEY_CTX *pctx,
+                              STACK_OF(OPENSSL_STRING) *param);
 
 # define SMIME_OP        0x10
 # define SMIME_IP        0x20
@@ -98,6 +100,14 @@ static CMS_ReceiptRequest *make_receipt_request(STACK_OF(OPENSSL_STRING)
 
 int verify_err = 0;
 
+typedef struct cms_key_param_st cms_key_param;
+
+struct cms_key_param_st {
+    int idx;
+    STACK_OF(OPENSSL_STRING) *param;
+    cms_key_param *next;
+};
+
 int MAIN(int, char **);
 
 int MAIN(int argc, char **argv)
@@ -112,7 +122,7 @@ int MAIN(int argc, char **argv)
     STACK_OF(OPENSSL_STRING) *sksigners = NULL, *skkeys = NULL;
     char *certfile = NULL, *keyfile = NULL, *contfile = NULL;
     char *certsoutfile = NULL;
-    const EVP_CIPHER *cipher = NULL;
+    const EVP_CIPHER *cipher = NULL, *wrap_cipher = NULL;
     CMS_ContentInfo *cms = NULL, *rcms = NULL;
     X509_STORE *store = NULL;
     X509 *cert = NULL, *recip = NULL, *signer = NULL;
@@ -140,6 +150,8 @@ int MAIN(int argc, char **argv)
     unsigned char *pwri_pass = NULL, *pwri_tmp = NULL;
     size_t secret_keylen = 0, secret_keyidlen = 0;
 
+    cms_key_param *key_first = NULL, *key_param = NULL;
+
     ASN1_OBJECT *econtent_type = NULL;
 
     X509_VERIFY_PARAM *vpm = NULL;
@@ -201,6 +213,8 @@ int MAIN(int argc, char **argv)
             cipher = EVP_des_ede3_cbc();
         else if (!strcmp(*args, "-des"))
             cipher = EVP_des_cbc();
+        else if (!strcmp(*args, "-des3-wrap"))
+            wrap_cipher = EVP_des_ede3_wrap();
 # endif
 # ifndef OPENSSL_NO_SEED
         else if (!strcmp(*args, "-seed"))
@@ -221,6 +235,12 @@ int MAIN(int argc, char **argv)
             cipher = EVP_aes_192_cbc();
         else if (!strcmp(*args, "-aes256"))
             cipher = EVP_aes_256_cbc();
+        else if (!strcmp(*args, "-aes128-wrap"))
+            wrap_cipher = EVP_aes_128_wrap();
+        else if (!strcmp(*args, "-aes192-wrap"))
+            wrap_cipher = EVP_aes_192_wrap();
+        else if (!strcmp(*args, "-aes256-wrap"))
+            wrap_cipher = EVP_aes_256_wrap();
 # endif
 # ifndef OPENSSL_NO_CAMELLIA
         else if (!strcmp(*args, "-camellia128"))
@@ -378,7 +398,17 @@ int MAIN(int argc, char **argv)
         } else if (!strcmp(*args, "-recip")) {
             if (!args[1])
                 goto argerr;
-            recipfile = *++args;
+            if (operation == SMIME_ENCRYPT) {
+                if (!encerts)
+                    encerts = sk_X509_new_null();
+                cert = load_cert(bio_err, *++args, FORMAT_PEM,
+                                 NULL, e, "recipient certificate file");
+                if (!cert)
+                    goto end;
+                sk_X509_push(encerts, cert);
+                cert = NULL;
+            } else
+                recipfile = *++args;
         } else if (!strcmp(*args, "-certsout")) {
             if (!args[1])
                 goto argerr;
@@ -413,6 +443,40 @@ int MAIN(int argc, char **argv)
             if (!args[1])
                 goto argerr;
             keyform = str2fmt(*++args);
+        } else if (!strcmp(*args, "-keyopt")) {
+            int keyidx = -1;
+            if (!args[1])
+                goto argerr;
+            if (operation == SMIME_ENCRYPT) {
+                if (encerts)
+                    keyidx += sk_X509_num(encerts);
+            } else {
+                if (keyfile || signerfile)
+                    keyidx++;
+                if (skkeys)
+                    keyidx += sk_OPENSSL_STRING_num(skkeys);
+            }
+            if (keyidx < 0) {
+                BIO_printf(bio_err, "No key specified\n");
+                goto argerr;
+            }
+            if (key_param == NULL || key_param->idx != keyidx) {
+                cms_key_param *nparam;
+                nparam = OPENSSL_malloc(sizeof(cms_key_param));
+                if (!nparam) {
+                    BIO_printf(bio_err, "Out of memory\n");
+                    goto argerr;
+                }
+                nparam->idx = keyidx;
+                nparam->param = sk_OPENSSL_STRING_new_null();
+                nparam->next = NULL;
+                if (key_first == NULL)
+                    key_first = nparam;
+                else
+                    key_param->next = nparam;
+                key_param = nparam;
+            }
+            sk_OPENSSL_STRING_push(key_param->param, *++args);
         } else if (!strcmp(*args, "-rctform")) {
             if (!args[1])
                 goto argerr;
@@ -502,7 +566,7 @@ int MAIN(int argc, char **argv)
             badarg = 1;
         }
     } else if (operation == SMIME_ENCRYPT) {
-        if (!*args && !secret_key && !pwri_pass) {
+        if (!*args && !secret_key && !pwri_pass && !encerts) {
             BIO_printf(bio_err, "No recipient(s) certificate(s) specified\n");
             badarg = 1;
         }
@@ -567,6 +631,7 @@ int MAIN(int argc, char **argv)
                    "-inkey file    input private key (if not signer or recipient)\n");
         BIO_printf(bio_err,
                    "-keyform arg   input private key format (PEM or ENGINE)\n");
+        BIO_printf(bio_err, "-keyopt nm:v   set public key parameters\n");
         BIO_printf(bio_err, "-out file      output file\n");
         BIO_printf(bio_err,
                    "-outform arg   output format SMIME (default), PEM or DER\n");
@@ -652,7 +717,7 @@ int MAIN(int argc, char **argv)
             goto end;
         }
 
-        if (*args)
+        if (*args && !encerts)
             encerts = sk_X509_new_null();
         while (*args) {
             if (!(cert = load_cert(bio_err, *args, FORMAT_PEM,
@@ -804,10 +869,39 @@ int MAIN(int argc, char **argv)
     } else if (operation == SMIME_COMPRESS) {
         cms = CMS_compress(in, -1, flags);
     } else if (operation == SMIME_ENCRYPT) {
+        int i;
         flags |= CMS_PARTIAL;
-        cms = CMS_encrypt(encerts, in, cipher, flags);
+        cms = CMS_encrypt(NULL, in, cipher, flags);
         if (!cms)
             goto end;
+        for (i = 0; i < sk_X509_num(encerts); i++) {
+            CMS_RecipientInfo *ri;
+            cms_key_param *kparam;
+            int tflags = flags;
+            X509 *x = sk_X509_value(encerts, i);
+            for (kparam = key_first; kparam; kparam = kparam->next) {
+                if (kparam->idx == i) {
+                    tflags |= CMS_KEY_PARAM;
+                    break;
+                }
+            }
+            ri = CMS_add1_recipient_cert(cms, x, tflags);
+            if (!ri)
+                goto end;
+            if (kparam) {
+                EVP_PKEY_CTX *pctx;
+                pctx = CMS_RecipientInfo_get0_pkey_ctx(ri);
+                if (!cms_set_pkey_param(pctx, kparam->param))
+                    goto end;
+            }
+            if (CMS_RecipientInfo_type(ri) == CMS_RECIPINFO_AGREE
+                && wrap_cipher) {
+                EVP_CIPHER_CTX *wctx;
+                wctx = CMS_RecipientInfo_kari_get0_ctx(ri);
+                EVP_EncryptInit_ex(wctx, wrap_cipher, NULL, NULL, NULL);
+            }
+        }
+
         if (secret_key) {
             if (!CMS_add0_recipient_key(cms, NID_undef,
                                         secret_key, secret_keylen,
@@ -880,8 +974,11 @@ int MAIN(int argc, char **argv)
             flags |= CMS_REUSE_DIGEST;
         for (i = 0; i < sk_OPENSSL_STRING_num(sksigners); i++) {
             CMS_SignerInfo *si;
+            cms_key_param *kparam;
+            int tflags = flags;
             signerfile = sk_OPENSSL_STRING_value(sksigners, i);
             keyfile = sk_OPENSSL_STRING_value(skkeys, i);
+
             signer = load_cert(bio_err, signerfile, FORMAT_PEM, NULL,
                                e, "signer certificate");
             if (!signer)
@@ -890,9 +987,21 @@ int MAIN(int argc, char **argv)
                            "signing key file");
             if (!key)
                 goto end;
-            si = CMS_add1_signer(cms, signer, key, sign_md, flags);
+            for (kparam = key_first; kparam; kparam = kparam->next) {
+                if (kparam->idx == i) {
+                    tflags |= CMS_KEY_PARAM;
+                    break;
+                }
+            }
+            si = CMS_add1_signer(cms, signer, key, sign_md, tflags);
             if (!si)
                 goto end;
+            if (kparam) {
+                EVP_PKEY_CTX *pctx;
+                pctx = CMS_SignerInfo_get0_pkey_ctx(si);
+                if (!cms_set_pkey_param(pctx, kparam->param))
+                    goto end;
+            }
             if (rr && !CMS_add1_ReceiptRequest(si, rr))
                 goto end;
             X509_free(signer);
@@ -1047,6 +1156,13 @@ int MAIN(int argc, char **argv)
         sk_OPENSSL_STRING_free(rr_to);
     if (rr_from)
         sk_OPENSSL_STRING_free(rr_from);
+    for (key_param = key_first; key_param;) {
+        cms_key_param *tparam;
+        sk_OPENSSL_STRING_free(key_param->param);
+        tparam = key_param->next;
+        OPENSSL_free(key_param);
+        key_param = tparam;
+    }
     X509_STORE_free(store);
     X509_free(cert);
     X509_free(recip);
@@ -1220,4 +1336,22 @@ static CMS_ReceiptRequest *make_receipt_request(STACK_OF(OPENSSL_STRING)
     return NULL;
 }
 
+static int cms_set_pkey_param(EVP_PKEY_CTX *pctx,
+                              STACK_OF(OPENSSL_STRING) *param)
+{
+    char *keyopt;
+    int i;
+    if (sk_OPENSSL_STRING_num(param) <= 0)
+        return 1;
+    for (i = 0; i < sk_OPENSSL_STRING_num(param); i++) {
+        keyopt = sk_OPENSSL_STRING_value(param, i);
+        if (pkey_ctrl_string(pctx, keyopt) <= 0) {
+            BIO_printf(bio_err, "parameter error \"%s\"\n", keyopt);
+            ERR_print_errors(bio_err);
+            return 0;
+        }
+    }
+    return 1;
+}
+
 #endif
index 0a05870..c9c3a5f 100644 (file)
@@ -96,7 +96,6 @@ static const char *crl_usage[] = {
     NULL
 };
 
-static X509_CRL *load_crl(char *file, int format);
 static BIO *bio_out = NULL;
 
 int MAIN(int, char **);
@@ -106,10 +105,10 @@ int MAIN(int argc, char **argv)
     unsigned long nmflag = 0;
     X509_CRL *x = NULL;
     char *CAfile = NULL, *CApath = NULL;
-    int ret = 1, i, num, badops = 0;
+    int ret = 1, i, num, badops = 0, badsig = 0;
     BIO *out = NULL;
-    int informat, outformat;
-    char *infile = NULL, *outfile = NULL;
+    int informat, outformat, keyformat;
+    char *infile = NULL, *outfile = NULL, *crldiff = NULL, *keyfile = NULL;
     int hash = 0, issuer = 0, lastupdate = 0, nextupdate = 0, noout =
         0, text = 0;
 #ifndef OPENSSL_NO_MD5
@@ -147,6 +146,7 @@ int MAIN(int argc, char **argv)
 
     informat = FORMAT_PEM;
     outformat = FORMAT_PEM;
+    keyformat = FORMAT_PEM;
 
     argc--;
     argv++;
@@ -173,6 +173,18 @@ int MAIN(int argc, char **argv)
             if (--argc < 1)
                 goto bad;
             infile = *(++argv);
+        } else if (strcmp(*argv, "-gendelta") == 0) {
+            if (--argc < 1)
+                goto bad;
+            crldiff = *(++argv);
+        } else if (strcmp(*argv, "-key") == 0) {
+            if (--argc < 1)
+                goto bad;
+            keyfile = *(++argv);
+        } else if (strcmp(*argv, "-keyform") == 0) {
+            if (--argc < 1)
+                goto bad;
+            keyformat = str2fmt(*(++argv));
         } else if (strcmp(*argv, "-out") == 0) {
             if (--argc < 1)
                 goto bad;
@@ -214,6 +226,8 @@ int MAIN(int argc, char **argv)
             fingerprint = ++num;
         else if (strcmp(*argv, "-crlnumber") == 0)
             crlnumber = ++num;
+        else if (strcmp(*argv, "-badsig") == 0)
+            badsig = 1;
         else if ((md_alg = EVP_get_digestbyname(*argv + 1))) {
             /* ok */
             digest = md_alg;
@@ -281,6 +295,33 @@ int MAIN(int argc, char **argv)
             BIO_printf(bio_err, "verify OK\n");
     }
 
+    if (crldiff) {
+        X509_CRL *newcrl, *delta;
+        if (!keyfile) {
+            BIO_puts(bio_err, "Missing CRL signing key\n");
+            goto end;
+        }
+        newcrl = load_crl(crldiff, informat);
+        if (!newcrl)
+            goto end;
+        pkey = load_key(bio_err, keyfile, keyformat, 0, NULL, NULL,
+                        "CRL signing key");
+        if (!pkey) {
+            X509_CRL_free(newcrl);
+            goto end;
+        }
+        delta = X509_CRL_diff(x, newcrl, pkey, digest, 0);
+        X509_CRL_free(newcrl);
+        EVP_PKEY_free(pkey);
+        if (delta) {
+            X509_CRL_free(x);
+            x = delta;
+        } else {
+            BIO_puts(bio_err, "Error creating delta CRL\n");
+            goto end;
+        }
+    }
+
     if (num) {
         for (i = 1; i <= num; i++) {
             if (issuer == i) {
@@ -369,6 +410,9 @@ int MAIN(int argc, char **argv)
         goto end;
     }
 
+    if (badsig)
+        x->signature->data[x->signature->length - 1] ^= 0x1;
+
     if (outformat == FORMAT_ASN1)
         i = (int)i2d_X509_CRL_bio(out, x);
     else if (outformat == FORMAT_PEM)
@@ -383,6 +427,8 @@ int MAIN(int argc, char **argv)
     }
     ret = 0;
  end:
+    if (ret != 0)
+        ERR_print_errors(bio_err);
     BIO_free_all(out);
     BIO_free_all(bio_out);
     bio_out = NULL;
@@ -394,41 +440,3 @@ int MAIN(int argc, char **argv)
     apps_shutdown();
     OPENSSL_EXIT(ret);
 }
-
-static X509_CRL *load_crl(char *infile, int format)
-{
-    X509_CRL *x = NULL;
-    BIO *in = NULL;
-
-    in = BIO_new(BIO_s_file());
-    if (in == NULL) {
-        ERR_print_errors(bio_err);
-        goto end;
-    }
-
-    if (infile == NULL)
-        BIO_set_fp(in, stdin, BIO_NOCLOSE);
-    else {
-        if (BIO_read_filename(in, infile) <= 0) {
-            perror(infile);
-            goto end;
-        }
-    }
-    if (format == FORMAT_ASN1)
-        x = d2i_X509_CRL_bio(in, NULL);
-    else if (format == FORMAT_PEM)
-        x = PEM_read_bio_X509_CRL(in, NULL, NULL, NULL);
-    else {
-        BIO_printf(bio_err, "bad input format specified for input crl\n");
-        goto end;
-    }
-    if (x == NULL) {
-        BIO_printf(bio_err, "unable to load CRL\n");
-        ERR_print_errors(bio_err);
-        goto end;
-    }
-
- end:
-    BIO_free(in);
-    return (x);
-}
index ad2f234..95e5fa3 100644 (file)
@@ -103,7 +103,7 @@ int MAIN(int, char **);
 
 int MAIN(int argc, char **argv)
 {
-    ENGINE *e = NULL;
+    ENGINE *e = NULL, *impl = NULL;
     unsigned char *buf = NULL;
     int i, err = 1;
     const EVP_MD *md = NULL, *m;
@@ -124,6 +124,7 @@ int MAIN(int argc, char **argv)
     char *passargin = NULL, *passin = NULL;
 #ifndef OPENSSL_NO_ENGINE
     char *engine = NULL;
+    int engine_impl = 0;
 #endif
     char *hmac_key = NULL;
     char *mac_name = NULL;
@@ -199,7 +200,8 @@ int MAIN(int argc, char **argv)
                 break;
             engine = *(++argv);
             e = setup_engine(bio_err, engine, 0);
-        }
+        } else if (strcmp(*argv, "-engine_impl") == 0)
+            engine_impl = 1;
 #endif
         else if (strcmp(*argv, "-hex") == 0)
             out_bin = 0;
@@ -284,6 +286,10 @@ int MAIN(int argc, char **argv)
         EVP_MD_do_all_sorted(list_md_fn, bio_err);
         goto end;
     }
+#ifndef OPENSSL_NO_ENGINE
+    if (engine_impl)
+        impl = e;
+#endif
 
     in = BIO_new(BIO_s_file());
     bmd = BIO_new(BIO_f_md());
@@ -357,7 +363,7 @@ int MAIN(int argc, char **argv)
     if (mac_name) {
         EVP_PKEY_CTX *mac_ctx = NULL;
         int r = 0;
-        if (!init_gen_str(bio_err, &mac_ctx, mac_name, e, 0))
+        if (!init_gen_str(bio_err, &mac_ctx, mac_name, impl, 0))
             goto mac_end;
         if (macopts) {
             char *macopt;
@@ -391,7 +397,7 @@ int MAIN(int argc, char **argv)
     }
 
     if (hmac_key) {
-        sigkey = EVP_PKEY_new_mac_key(EVP_PKEY_HMAC, e,
+        sigkey = EVP_PKEY_new_mac_key(EVP_PKEY_HMAC, impl,
                                       (unsigned char *)hmac_key, -1);
         if (!sigkey)
             goto end;
@@ -407,9 +413,9 @@ int MAIN(int argc, char **argv)
             goto end;
         }
         if (do_verify)
-            r = EVP_DigestVerifyInit(mctx, &pctx, md, NULL, sigkey);
+            r = EVP_DigestVerifyInit(mctx, &pctx, md, impl, sigkey);
         else
-            r = EVP_DigestSignInit(mctx, &pctx, md, NULL, sigkey);
+            r = EVP_DigestSignInit(mctx, &pctx, md, impl, sigkey);
         if (!r) {
             BIO_printf(bio_err, "Error setting context\n");
             ERR_print_errors(bio_err);
@@ -429,9 +435,15 @@ int MAIN(int argc, char **argv)
     }
     /* we use md as a filter, reading from 'in' */
     else {
+        EVP_MD_CTX *mctx = NULL;
+        if (!BIO_get_md_ctx(bmd, &mctx)) {
+            BIO_printf(bio_err, "Error getting context\n");
+            ERR_print_errors(bio_err);
+            goto end;
+        }
         if (md == NULL)
             md = EVP_md5();
-        if (!BIO_set_md(bmd, md)) {
+        if (!EVP_DigestInit_ex(mctx, md, impl)) {
             BIO_printf(bio_err, "Error setting digest %s\n", pname);
             ERR_print_errors(bio_err);
             goto end;
@@ -483,7 +495,8 @@ int MAIN(int argc, char **argv)
                     EVP_PKEY_asn1_get0_info(NULL, NULL,
                                             NULL, NULL, &sig_name, ameth);
             }
-            md_name = EVP_MD_name(md);
+            if (md)
+                md_name = EVP_MD_name(md);
         }
         err = 0;
         for (i = 0; i < argc; i++) {
@@ -581,9 +594,12 @@ int do_fp(BIO *out, unsigned char *buf, BIO *bp, int sep, int binout,
             BIO_printf(out, "%02x", buf[i]);
         BIO_printf(out, " *%s\n", file);
     } else {
-        if (sig_name)
-            BIO_printf(out, "%s-%s(%s)= ", sig_name, md_name, file);
-        else if (md_name)
+        if (sig_name) {
+            BIO_puts(out, sig_name);
+            if (md_name)
+                BIO_printf(out, "-%s", md_name);
+            BIO_printf(out, "(%s)= ", file);
+        } else if (md_name)
             BIO_printf(out, "%s(%s)= ", md_name, file);
         else
             BIO_printf(out, "(%s)= ", file);
index d3b6d58..57199a8 100644 (file)
@@ -489,9 +489,12 @@ int MAIN(int argc, char **argv)
     if (!noout) {
         if (outformat == FORMAT_ASN1)
             i = i2d_DHparams_bio(out, dh);
-        else if (outformat == FORMAT_PEM)
-            i = PEM_write_bio_DHparams(out, dh);
-        else {
+        else if (outformat == FORMAT_PEM) {
+            if (dh->q)
+                i = PEM_write_bio_DHxparams(out, dh);
+            else
+                i = PEM_write_bio_DHparams(out, dh);
+        } else {
             BIO_printf(bio_err, "bad output format specified for outfile\n");
             goto end;
         }
index 402fb31..71b67f4 100644 (file)
@@ -370,6 +370,9 @@ int MAIN(int argc, char **argv)
         } else
             nid = OBJ_sn2nid(curve_name);
 
+        if (nid == 0)
+            nid = EC_curve_nist2nid(curve_name);
+
         if (nid == 0) {
             BIO_printf(bio_err, "unknown curve name (%s)\n", curve_name);
             goto end;
index 2eabadc..91e6550 100644 (file)
@@ -80,7 +80,7 @@
 # include <openssl/pem.h>
 # include <openssl/rand.h>
 
-# define DEFBITS 1024
+# define DEFBITS 2048
 # undef PROG
 # define PROG genrsa_main
 
index bb420c2..5da51df 100644 (file)
@@ -110,16 +110,17 @@ static int print_ocsp_summary(BIO *out, OCSP_BASICRESP *bs, OCSP_REQUEST *req,
 
 static int make_ocsp_response(OCSP_RESPONSE **resp, OCSP_REQUEST *req,
                               CA_DB *db, X509 *ca, X509 *rcert,
-                              EVP_PKEY *rkey, STACK_OF(X509) *rother,
-                              unsigned long flags, int nmin, int ndays);
+                              EVP_PKEY *rkey, const EVP_MD *md,
+                              STACK_OF(X509) *rother, unsigned long flags,
+                              int nmin, int ndays, int badsig);
 
 static char **lookup_serial(CA_DB *db, ASN1_INTEGER *ser);
-static BIO *init_responder(char *port);
+static BIO *init_responder(const char *port);
 static int do_responder(OCSP_REQUEST **preq, BIO **pcbio, BIO *acbio,
-                        char *port);
+                        const char *port);
 static int send_ocsp_response(BIO *cbio, OCSP_RESPONSE *resp);
-static OCSP_RESPONSE *query_responder(BIO *err, BIO *cbio, char *path,
-                                      STACK_OF(CONF_VALUE) *headers,
+static OCSP_RESPONSE *query_responder(BIO *err, BIO *cbio, const char *path,
+                                      const STACK_OF(CONF_VALUE) *headers,
                                       OCSP_REQUEST *req, int req_timeout);
 
 # undef PROG
@@ -154,12 +155,14 @@ int MAIN(int argc, char **argv)
     long nsec = MAX_VALIDITY_PERIOD, maxage = -1;
     char *CAfile = NULL, *CApath = NULL;
     X509_STORE *store = NULL;
+    X509_VERIFY_PARAM *vpm = 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;
     int ret = 1;
     int accept_count = -1;
     int badarg = 0;
+    int badsig = 0;
     int i;
     int ignore_err = 0;
     STACK_OF(OPENSSL_STRING) *reqnames = NULL;
@@ -170,7 +173,7 @@ int MAIN(int argc, char **argv)
     char *rca_filename = NULL;
     CA_DB *rdb = NULL;
     int nmin = 0, ndays = -1;
-    const EVP_MD *cert_id_md = NULL;
+    const EVP_MD *cert_id_md = NULL, *rsign_md = NULL;
 
     if (bio_err == NULL)
         bio_err = BIO_new_fp(stderr, BIO_NOCLOSE);
@@ -206,6 +209,7 @@ int MAIN(int argc, char **argv)
                 OPENSSL_free(tport);
             if (tpath)
                 OPENSSL_free(tpath);
+            thost = tport = tpath = NULL;
             if (args[1]) {
                 args++;
                 if (!OCSP_parse_url(*args, &host, &port, &path, &use_ssl)) {
@@ -264,6 +268,8 @@ int MAIN(int argc, char **argv)
             verify_flags |= OCSP_TRUSTOTHER;
         else if (!strcmp(*args, "-no_intern"))
             verify_flags |= OCSP_NOINTERN;
+        else if (!strcmp(*args, "-badsig"))
+            badsig = 1;
         else if (!strcmp(*args, "-text")) {
             req_text = 1;
             resp_text = 1;
@@ -320,6 +326,10 @@ int MAIN(int argc, char **argv)
                 CApath = *args;
             } else
                 badarg = 1;
+        } else if (args_verify(&args, NULL, &badarg, bio_err, &vpm)) {
+            if (badarg)
+                goto end;
+            continue;
         } else if (!strcmp(*args, "-validity_period")) {
             if (args[1]) {
                 args++;
@@ -465,6 +475,14 @@ int MAIN(int argc, char **argv)
                 rcertfile = *args;
             } else
                 badarg = 1;
+        } else if (!strcmp(*args, "-rmd")) {
+            if (args[1]) {
+                args++;
+                rsign_md = EVP_get_digestbyname(*args);
+                if (!rsign_md)
+                    badarg = 1;
+            } else
+                badarg = 1;
         } else if ((cert_id_md = EVP_get_digestbyname((*args) + 1)) == NULL) {
             badarg = 1;
         }
@@ -584,7 +602,10 @@ int MAIN(int argc, char **argv)
         add_nonce = 0;
 
     if (!req && reqin) {
-        derbio = BIO_new_file(reqin, "rb");
+        if (!strcmp(reqin, "-"))
+            derbio = BIO_new_fp(stdin, BIO_NOCLOSE);
+        else
+            derbio = BIO_new_file(reqin, "rb");
         if (!derbio) {
             BIO_printf(bio_err, "Error Opening OCSP request file\n");
             goto end;
@@ -681,7 +702,10 @@ int MAIN(int argc, char **argv)
         OCSP_REQUEST_print(out, req, 0);
 
     if (reqout) {
-        derbio = BIO_new_file(reqout, "wb");
+        if (!strcmp(reqout, "-"))
+            derbio = BIO_new_fp(stdout, BIO_NOCLOSE);
+        else
+            derbio = BIO_new_file(reqout, "wb");
         if (!derbio) {
             BIO_printf(bio_err, "Error opening file %s\n", reqout);
             goto end;
@@ -706,7 +730,7 @@ int MAIN(int argc, char **argv)
 
     if (rdb) {
         i = make_ocsp_response(&resp, req, rdb, rca_cert, rsigner, rkey,
-                               rother, rflags, nmin, ndays);
+                               rsign_md, rother, rflags, nmin, ndays, badsig);
         if (cbio)
             send_ocsp_response(cbio, resp);
     } else if (host) {
@@ -721,7 +745,10 @@ int MAIN(int argc, char **argv)
         goto end;
 # endif
     } else if (respin) {
-        derbio = BIO_new_file(respin, "rb");
+        if (!strcmp(respin, "-"))
+            derbio = BIO_new_fp(stdin, BIO_NOCLOSE);
+        else
+            derbio = BIO_new_file(respin, "rb");
         if (!derbio) {
             BIO_printf(bio_err, "Error Opening OCSP response file\n");
             goto end;
@@ -741,7 +768,10 @@ int MAIN(int argc, char **argv)
  done_resp:
 
     if (respout) {
-        derbio = BIO_new_file(respout, "wb");
+        if (!strcmp(respout, "-"))
+            derbio = BIO_new_fp(stdout, BIO_NOCLOSE);
+        else
+            derbio = BIO_new_file(respout, "wb");
         if (!derbio) {
             BIO_printf(bio_err, "Error opening file %s\n", respout);
             goto end;
@@ -778,6 +808,10 @@ int MAIN(int argc, char **argv)
             resp = NULL;
             goto redo_accept;
         }
+        ret = 0;
+        goto end;
+    } else if (ridx_filename) {
+        ret = 0;
         goto end;
     }
 
@@ -785,6 +819,8 @@ int MAIN(int argc, char **argv)
         store = setup_verify(bio_err, CAfile, CApath);
     if (!store)
         goto end;
+    if (vpm)
+        X509_STORE_set1_param(store, vpm);
     if (verify_certfile) {
         verify_other = load_certs(bio_err, verify_certfile, FORMAT_PEM,
                                   NULL, e, "validator certificate");
@@ -799,37 +835,38 @@ int MAIN(int argc, char **argv)
         goto end;
     }
 
+    ret = 0;
+
     if (!noverify) {
         if (req && ((i = OCSP_check_nonce(req, bs)) <= 0)) {
             if (i == -1)
                 BIO_printf(bio_err, "WARNING: no nonce in response\n");
             else {
                 BIO_printf(bio_err, "Nonce Verify error\n");
+                ret = 1;
                 goto end;
             }
         }
 
         i = OCSP_basic_verify(bs, verify_other, store, verify_flags);
-        if (i < 0)
-            i = OCSP_basic_verify(bs, NULL, store, 0);
-
         if (i <= 0) {
             BIO_printf(bio_err, "Response Verify Failure\n");
             ERR_print_errors(bio_err);
+            ret = 1;
         } else
             BIO_printf(bio_err, "Response verify OK\n");
 
     }
 
     if (!print_ocsp_summary(out, bs, req, reqnames, ids, nsec, maxage))
-        goto end;
-
-    ret = 0;
+        ret = 1;
 
  end:
     ERR_print_errors(bio_err);
     X509_free(signer);
     X509_STORE_free(store);
+    if (vpm)
+        X509_VERIFY_PARAM_free(vpm);
     EVP_PKEY_free(key);
     EVP_PKEY_free(rkey);
     X509_free(issuer);
@@ -984,8 +1021,9 @@ static int print_ocsp_summary(BIO *out, OCSP_BASICRESP *bs, OCSP_REQUEST *req,
 
 static int make_ocsp_response(OCSP_RESPONSE **resp, OCSP_REQUEST *req,
                               CA_DB *db, X509 *ca, X509 *rcert,
-                              EVP_PKEY *rkey, STACK_OF(X509) *rother,
-                              unsigned long flags, int nmin, int ndays)
+                              EVP_PKEY *rkey, const EVP_MD *rmd,
+                              STACK_OF(X509) *rother, unsigned long flags,
+                              int nmin, int ndays, int badsig)
 {
     ASN1_TIME *thisupd = NULL, *nextupd = NULL;
     OCSP_CERTID *cid, *ca_id = NULL;
@@ -1069,7 +1107,10 @@ static int make_ocsp_response(OCSP_RESPONSE **resp, OCSP_REQUEST *req,
 
     OCSP_copy_nonce(bs, req);
 
-    OCSP_basic_sign(bs, rcert, rkey, NULL, rother, flags);
+    OCSP_basic_sign(bs, rcert, rkey, rmd, rother, flags);
+
+    if (badsig)
+        bs->signature->data[bs->signature->length - 1] ^= 0x1;
 
     *resp = OCSP_response_create(OCSP_RESPONSE_STATUS_SUCCESSFUL, bs);
 
@@ -1105,7 +1146,7 @@ static char **lookup_serial(CA_DB *db, ASN1_INTEGER *ser)
 
 /* Quick and dirty OCSP server: read in and parse input request */
 
-static BIO *init_responder(char *port)
+static BIO *init_responder(const char *port)
 {
     BIO *acbio = NULL, *bufbio = NULL;
     bufbio = BIO_new(BIO_f_buffer());
@@ -1137,7 +1178,7 @@ static BIO *init_responder(char *port)
 }
 
 static int do_responder(OCSP_REQUEST **preq, BIO **pcbio, BIO *acbio,
-                        char *port)
+                        const char *port)
 {
     int have_post = 0, len;
     OCSP_REQUEST *req = NULL;
@@ -1198,8 +1239,8 @@ static int send_ocsp_response(BIO *cbio, OCSP_RESPONSE *resp)
     return 1;
 }
 
-static OCSP_RESPONSE *query_responder(BIO *err, BIO *cbio, char *path,
-                                      STACK_OF(CONF_VALUE) *headers,
+static OCSP_RESPONSE *query_responder(BIO *err, BIO *cbio, const char *path,
+                                      const STACK_OF(CONF_VALUE) *headers,
                                       OCSP_REQUEST *req, int req_timeout)
 {
     int fd;
@@ -1286,8 +1327,9 @@ static OCSP_RESPONSE *query_responder(BIO *err, BIO *cbio, char *path,
 }
 
 OCSP_RESPONSE *process_responder(BIO *err, OCSP_REQUEST *req,
-                                 char *host, char *path, char *port,
-                                 int use_ssl, STACK_OF(CONF_VALUE) *headers,
+                                 const char *host, const char *path,
+                                 const char *port, int use_ssl,
+                                 const STACK_OF(CONF_VALUE) *headers,
                                  int req_timeout)
 {
     BIO *cbio = NULL;
index 18760c6..1eb86c4 100644 (file)
@@ -103,7 +103,7 @@ emailAddress                = optional
 
 ####################################################################
 [ req ]
-default_bits           = 1024
+default_bits           = 2048
 default_keyfile        = privkey.pem
 distinguished_name     = req_distinguished_name
 attributes             = req_attributes
index 5c7290e..5099e18 100644 (file)
@@ -124,6 +124,16 @@ int MAIN(int argc, char **argv)
                 }
             } else
                 badarg = 1;
+        } else if (!strcmp(*args, "-v2prf")) {
+            if (args[1]) {
+                args++;
+                pbe_nid = OBJ_txt2nid(*args);
+                if (!EVP_PBE_find(EVP_PBE_TYPE_PRF, pbe_nid, NULL, NULL, 0)) {
+                    BIO_printf(bio_err, "Unknown PRF algorithm %s\n", *args);
+                    badarg = 1;
+                }
+            } else
+                badarg = 1;
         } else if (!strcmp(*args, "-inform")) {
             if (args[1]) {
                 args++;
index aaa9074..e47206c 100644 (file)
@@ -73,11 +73,12 @@ static void usage(void);
 #define PROG pkeyutl_main
 
 static EVP_PKEY_CTX *init_ctx(int *pkeysize,
-                              char *keyfile, int keyform, int key_type,
-                              char *passargin, int pkey_op, ENGINE *e);
+                              const char *keyfile, int keyform, int key_type,
+                              char *passargin, int pkey_op, ENGINE *e,
+                              int   impl);
 
 static int setup_peer(BIO *err, EVP_PKEY_CTX *ctx, int peerform,
-                      const char *file);
+                      const char *file, ENGINE* e);
 
 static int do_keyop(EVP_PKEY_CTX *ctx, int pkey_op,
                     unsigned char *out, size_t *poutlen,
@@ -97,10 +98,13 @@ int MAIN(int argc, char **argv)
     EVP_PKEY_CTX *ctx = NULL;
     char *passargin = NULL;
     int keysize = -1;
-
+    int engine_impl = 0;
     unsigned char *buf_in = NULL, *buf_out = NULL, *sig = NULL;
-    size_t buf_outlen;
+    size_t buf_outlen = 0;
     int buf_inlen = 0, siglen = -1;
+    const char *inkey = NULL;
+    const char *peerkey = NULL;
+    STACK_OF(OPENSSL_STRING) *pkeyopts = NULL;
 
     int ret = 1, rv = -1;
 
@@ -134,21 +138,13 @@ int MAIN(int argc, char **argv)
         } else if (!strcmp(*argv, "-inkey")) {
             if (--argc < 1)
                 badarg = 1;
-            else {
-                ctx = init_ctx(&keysize,
-                               *(++argv), keyform, key_type,
-                               passargin, pkey_op, e);
-                if (!ctx) {
-                    BIO_puts(bio_err, "Error initializing context\n");
-                    ERR_print_errors(bio_err);
-                    badarg = 1;
-                }
-            }
+            else
+                inkey = *++argv;
         } else if (!strcmp(*argv, "-peerkey")) {
             if (--argc < 1)
                 badarg = 1;
-            else if (!setup_peer(bio_err, ctx, peerform, *(++argv)))
-                badarg = 1;
+            else
+                peerkey = *++argv;
         } else if (!strcmp(*argv, "-passin")) {
             if (--argc < 1)
                 badarg = 1;
@@ -171,6 +167,8 @@ int MAIN(int argc, char **argv)
                 badarg = 1;
             else
                 e = setup_engine(bio_err, *(++argv), 0);
+        } else if (!strcmp(*argv, "-engine_impl")) {
+                engine_impl = 1;
         }
 #endif
         else if (!strcmp(*argv, "-pubin"))
@@ -187,23 +185,21 @@ int MAIN(int argc, char **argv)
             pkey_op = EVP_PKEY_OP_VERIFY;
         else if (!strcmp(*argv, "-verifyrecover"))
             pkey_op = EVP_PKEY_OP_VERIFYRECOVER;
-        else if (!strcmp(*argv, "-rev"))
-            rev = 1;
         else if (!strcmp(*argv, "-encrypt"))
             pkey_op = EVP_PKEY_OP_ENCRYPT;
         else if (!strcmp(*argv, "-decrypt"))
             pkey_op = EVP_PKEY_OP_DECRYPT;
         else if (!strcmp(*argv, "-derive"))
             pkey_op = EVP_PKEY_OP_DERIVE;
+        else if (!strcmp(*argv, "-rev"))
+            rev = 1;
         else if (strcmp(*argv, "-pkeyopt") == 0) {
             if (--argc < 1)
                 badarg = 1;
-            else if (!ctx) {
-                BIO_puts(bio_err, "-pkeyopt command before -inkey\n");
-                badarg = 1;
-            } else if (pkey_ctrl_string(ctx, *(++argv)) <= 0) {
-                BIO_puts(bio_err, "parameter setting error\n");
-                ERR_print_errors(bio_err);
+            else if ((pkeyopts == NULL &&
+                     (pkeyopts = sk_OPENSSL_STRING_new_null()) == NULL) ||
+                    sk_OPENSSL_STRING_push(pkeyopts, *++argv) == 0) {
+                BIO_puts(bio_err, "out of memory\n");
                 goto end;
             }
         } else
@@ -216,10 +212,37 @@ int MAIN(int argc, char **argv)
         argv++;
     }
 
-    if (!ctx) {
+    if (inkey == NULL ||
+        (peerkey != NULL && pkey_op != EVP_PKEY_OP_DERIVE)) {
         usage();
         goto end;
     }
+    ctx = init_ctx(&keysize, inkey, keyform, key_type,
+                   passargin, pkey_op, e, engine_impl);
+    if (!ctx) {
+        BIO_puts(bio_err, "Error initializing context\n");
+        ERR_print_errors(bio_err);
+        goto end;
+    }
+    if (peerkey != NULL && !setup_peer(bio_err, ctx, peerform, peerkey, e)) {
+        BIO_puts(bio_err, "Error setting up peer key\n");
+        ERR_print_errors(bio_err);
+        goto end;
+    }
+    if (pkeyopts != NULL) {
+        int num = sk_OPENSSL_STRING_num(pkeyopts);
+        int i;
+
+        for (i = 0; i < num; ++i) {
+            const char *opt = sk_OPENSSL_STRING_value(pkeyopts, i);
+
+            if (pkey_ctrl_string(ctx, opt) <= 0) {
+                BIO_puts(bio_err, "parameter setting error\n");
+                ERR_print_errors(bio_err);
+                goto end;
+            }
+        }
+    }
 
     if (sigfile && (pkey_op != EVP_PKEY_OP_VERIFY)) {
         BIO_puts(bio_err, "Signature file specified for non verify\n");
@@ -269,7 +292,7 @@ int MAIN(int argc, char **argv)
         }
         siglen = bio_to_mem(&sig, keysize * 10, sigbio);
         BIO_free(sigbio);
-        if (siglen <= 0) {
+        if (siglen < 0) {
             BIO_printf(bio_err, "Error reading signature data\n");
             goto end;
         }
@@ -278,7 +301,7 @@ int MAIN(int argc, char **argv)
     if (in) {
         /* Read the input data */
         buf_inlen = bio_to_mem(&buf_in, keysize * 10, in);
-        if (buf_inlen <= 0) {
+        if (buf_inlen < 0) {
             BIO_printf(bio_err, "Error reading input Data\n");
             exit(1);
         }
@@ -306,7 +329,7 @@ int MAIN(int argc, char **argv)
     } else {
         rv = do_keyop(ctx, pkey_op, NULL, (size_t *)&buf_outlen,
                       buf_in, (size_t)buf_inlen);
-        if (rv > 0) {
+        if (rv > 0 && buf_outlen != 0) {
             buf_out = OPENSSL_malloc(buf_outlen);
             if (!buf_out)
                 rv = -1;
@@ -336,12 +359,14 @@ int MAIN(int argc, char **argv)
         EVP_PKEY_CTX_free(ctx);
     BIO_free(in);
     BIO_free_all(out);
-    if (buf_in)
+    if (buf_in != NULL)
         OPENSSL_free(buf_in);
-    if (buf_out)
+    if (buf_out != NULL)
         OPENSSL_free(buf_out);
-    if (sig)
+    if (sig != NULL)
         OPENSSL_free(sig);
+    if (pkeyopts != NULL)
+        sk_OPENSSL_STRING_free(pkeyopts);
     return ret;
 }
 
@@ -368,18 +393,21 @@ static void usage()
     BIO_printf(bio_err, "-hexdump        hex dump output\n");
 #ifndef OPENSSL_NO_ENGINE
     BIO_printf(bio_err,
-               "-engine e       use engine e, possibly a hardware device.\n");
+               "-engine e       use engine e, maybe a hardware device, for loading keys.\n");
+    BIO_printf(bio_err, "-engine_impl    also use engine given by -engine for crypto operations\n");
 #endif
     BIO_printf(bio_err, "-passin arg     pass phrase source\n");
 
 }
 
 static EVP_PKEY_CTX *init_ctx(int *pkeysize,
-                              char *keyfile, int keyform, int key_type,
-                              char *passargin, int pkey_op, ENGINE *e)
+                              const char *keyfile, int keyform, int key_type,
+                              char *passargin, int pkey_op, ENGINE *e,
+                              int   engine_impl)
 {
     EVP_PKEY *pkey = NULL;
     EVP_PKEY_CTX *ctx = NULL;
+    ENGINE *impl = NULL;
     char *passin = NULL;
     int rv = -1;
     X509 *x;
@@ -418,9 +446,14 @@ static EVP_PKEY_CTX *init_ctx(int *pkeysize,
 
     if (!pkey)
         goto end;
-
-    ctx = EVP_PKEY_CTX_new(pkey, e);
-
+        
+#ifndef OPENSSL_NO_ENGINE
+    if (engine_impl)
+       impl = e;
+#endif
+            
+    ctx = EVP_PKEY_CTX_new(pkey, impl);
+    
     EVP_PKEY_free(pkey);
 
     if (!ctx)
@@ -467,16 +500,15 @@ static EVP_PKEY_CTX *init_ctx(int *pkeysize,
 }
 
 static int setup_peer(BIO *err, EVP_PKEY_CTX *ctx, int peerform,
-                      const char *file)
+                      const char *file, ENGINE* e)
 {
     EVP_PKEY *peer = NULL;
+    ENGINE* engine = NULL;
     int ret;
-    if (!ctx) {
-        BIO_puts(err, "-peerkey command before -inkey\n");
-        return 0;
-    }
 
-    peer = load_pubkey(bio_err, file, peerform, 0, NULL, NULL, "Peer Key");
+    if (peerform == FORMAT_ENGINE)
+        engine = e;
+    peer = load_pubkey(bio_err, file, peerform, 0, NULL, engine, "Peer Key");
 
     if (!peer) {
         BIO_printf(bio_err, "Error reading peer key %s\n", file);
index 57781c9..e818bd2 100644 (file)
 #define STRING_MASK     "string_mask"
 #define UTF8_IN         "utf8"
 
-#define DEFAULT_KEY_LENGTH      512
-#define MIN_KEY_LENGTH          384
+#define DEFAULT_KEY_LENGTH      2048
+#define MIN_KEY_LENGTH          512
 
 #undef PROG
 #define PROG    req_main
index d642f9a..5b6f849 100644 (file)
@@ -250,7 +250,7 @@ int MAIN(int argc, char **argv)
 
     if (outfile) {
         if (!(out = BIO_new_file(outfile, "wb"))) {
-            BIO_printf(bio_err, "Error Reading Output File\n");
+            BIO_printf(bio_err, "Error Writing Output File\n");
             ERR_print_errors(bio_err);
             goto end;
         }
@@ -276,7 +276,7 @@ int MAIN(int argc, char **argv)
 
     /* Read the input data */
     rsa_inlen = BIO_read(in, rsa_in, keysize * 2);
-    if (rsa_inlen <= 0) {
+    if (rsa_inlen < 0) {
         BIO_printf(bio_err, "Error reading input Data\n");
         exit(1);
     }
@@ -311,7 +311,7 @@ int MAIN(int argc, char **argv)
 
     }
 
-    if (rsa_outlen <= 0) {
+    if (rsa_outlen < 0) {
         BIO_printf(bio_err, "RSA operation error\n");
         ERR_print_errors(bio_err);
         goto end;
index 2769b89..5b54bfd 100644 (file)
@@ -152,15 +152,21 @@ typedef fd_mask fd_set;
 #define PROTOCOL        "tcp"
 
 int do_server(int port, int type, int *ret,
-              int (*cb) (char *hostname, int s, unsigned char *context),
-              unsigned char *context);
+              int (*cb) (char *hostname, int s, int stype,
+                         unsigned char *context), unsigned char *context,
+              int naccept);
 #ifdef HEADER_X509_H
 int MS_CALLBACK verify_callback(int ok, X509_STORE_CTX *ctx);
 #endif
 #ifdef HEADER_SSL_H
 int set_cert_stuff(SSL_CTX *ctx, char *cert_file, char *key_file);
-int set_cert_key_stuff(SSL_CTX *ctx, X509 *cert, EVP_PKEY *key);
+int set_cert_key_stuff(SSL_CTX *ctx, X509 *cert, EVP_PKEY *key,
+                       STACK_OF(X509) *chain, int build_chain);
+int ssl_print_sigalgs(BIO *out, SSL *s);
+int ssl_print_point_formats(BIO *out, SSL *s);
+int ssl_print_curves(BIO *out, SSL *s, int noshared);
 #endif
+int ssl_print_tmp_key(BIO *out, SSL *s);
 int init_client(int *sock, char *server, int port, int type);
 int should_retry(int i);
 int extract_port(char *str, short *port_ptr);
@@ -182,3 +188,24 @@ int MS_CALLBACK generate_cookie_callback(SSL *ssl, unsigned char *cookie,
                                          unsigned int *cookie_len);
 int MS_CALLBACK verify_cookie_callback(SSL *ssl, unsigned char *cookie,
                                        unsigned int cookie_len);
+
+typedef struct ssl_excert_st SSL_EXCERT;
+
+void ssl_ctx_set_excert(SSL_CTX *ctx, SSL_EXCERT *exc);
+void ssl_excert_free(SSL_EXCERT *exc);
+int args_excert(char ***pargs, int *pargc,
+                int *badarg, BIO *err, SSL_EXCERT **pexc);
+int load_excert(SSL_EXCERT **pexc, BIO *err);
+void print_ssl_summary(BIO *bio, SSL *s);
+#ifdef HEADER_SSL_H
+int args_ssl(char ***pargs, int *pargc, SSL_CONF_CTX *cctx,
+             int *badarg, BIO *err, STACK_OF(OPENSSL_STRING) **pstr);
+int args_ssl_call(SSL_CTX *ctx, BIO *err, SSL_CONF_CTX *cctx,
+                  STACK_OF(OPENSSL_STRING) *str, int no_ecdhe, int no_jpake);
+int ssl_ctx_add_crls(SSL_CTX *ctx, STACK_OF(X509_CRL) *crls,
+                     int crl_download);
+int ssl_load_stores(SSL_CTX *ctx, const char *vfyCApath,
+                    const char *vfyCAfile, const char *chCApath,
+                    const char *chCAfile, STACK_OF(X509_CRL) *crls,
+                    int crl_download);
+#endif
index fabf9cf..5b5e711 100644 (file)
 
 #include <stdio.h>
 #include <stdlib.h>
-#include <string.h> /* for memcpy() */
+#include <string.h> /* for memcpy() and strcmp() */
 #define USE_SOCKETS
 #define NON_MAIN
 #include "apps.h"
 #define COOKIE_SECRET_LENGTH    16
 
 int verify_depth = 0;
+int verify_quiet = 0;
 int verify_error = X509_V_OK;
 int verify_return_error = 0;
 unsigned char cookie_secret[COOKIE_SECRET_LENGTH];
@@ -140,13 +141,16 @@ int MS_CALLBACK verify_callback(int ok, X509_STORE_CTX *ctx)
     err = X509_STORE_CTX_get_error(ctx);
     depth = X509_STORE_CTX_get_error_depth(ctx);
 
-    BIO_printf(bio_err, "depth=%d ", depth);
-    if (err_cert) {
-        X509_NAME_print_ex(bio_err, X509_get_subject_name(err_cert),
-                           0, XN_FLAG_ONELINE);
-        BIO_puts(bio_err, "\n");
-    } else
-        BIO_puts(bio_err, "<no cert>\n");
+    if (!verify_quiet || !ok) {
+        BIO_printf(bio_err, "depth=%d ", depth);
+        if (err_cert) {
+            X509_NAME_print_ex(bio_err,
+                               X509_get_subject_name(err_cert),
+                               0, XN_FLAG_ONELINE);
+            BIO_puts(bio_err, "\n");
+        } else
+            BIO_puts(bio_err, "<no cert>\n");
+    }
     if (!ok) {
         BIO_printf(bio_err, "verify error:num=%d:%s\n", err,
                    X509_verify_cert_error_string(err));
@@ -179,13 +183,14 @@ int MS_CALLBACK verify_callback(int ok, X509_STORE_CTX *ctx)
         BIO_printf(bio_err, "\n");
         break;
     case X509_V_ERR_NO_EXPLICIT_POLICY:
-        policies_print(bio_err, ctx);
+        if (!verify_quiet)
+            policies_print(bio_err, ctx);
         break;
     }
-    if (err == X509_V_OK && ok == 2)
+    if (err == X509_V_OK && ok == 2 && !verify_quiet)
         policies_print(bio_err, ctx);
-
-    BIO_printf(bio_err, "verify return:%d\n", ok);
+    if (ok && !verify_quiet)
+        BIO_printf(bio_err, "verify return:%d\n", ok);
     return (ok);
 }
 
@@ -246,8 +251,10 @@ int set_cert_stuff(SSL_CTX *ctx, char *cert_file, char *key_file)
     return (1);
 }
 
-int set_cert_key_stuff(SSL_CTX *ctx, X509 *cert, EVP_PKEY *key)
+int set_cert_key_stuff(SSL_CTX *ctx, X509 *cert, EVP_PKEY *key,
+                       STACK_OF(X509) *chain, int build_chain)
 {
+    int chflags = chain ? SSL_BUILD_CHAIN_FLAG_CHECK : 0;
     if (cert == NULL)
         return 1;
     if (SSL_CTX_use_certificate(ctx, cert) <= 0) {
@@ -255,6 +262,7 @@ int set_cert_key_stuff(SSL_CTX *ctx, X509 *cert, EVP_PKEY *key)
         ERR_print_errors(bio_err);
         return 0;
     }
+
     if (SSL_CTX_use_PrivateKey(ctx, key) <= 0) {
         BIO_printf(bio_err, "error setting private key\n");
         ERR_print_errors(bio_err);
@@ -269,6 +277,263 @@ int set_cert_key_stuff(SSL_CTX *ctx, X509 *cert, EVP_PKEY *key)
                    "Private key does not match the certificate public key\n");
         return 0;
     }
+    if (chain && !SSL_CTX_set1_chain(ctx, chain)) {
+        BIO_printf(bio_err, "error setting certificate chain\n");
+        ERR_print_errors(bio_err);
+        return 0;
+    }
+    if (build_chain && !SSL_CTX_build_cert_chain(ctx, chflags)) {
+        BIO_printf(bio_err, "error building certificate chain\n");
+        ERR_print_errors(bio_err);
+        return 0;
+    }
+    return 1;
+}
+
+static void ssl_print_client_cert_types(BIO *bio, SSL *s)
+{
+    const unsigned char *p;
+    int i;
+    int cert_type_num = SSL_get0_certificate_types(s, &p);
+    if (!cert_type_num)
+        return;
+    BIO_puts(bio, "Client Certificate Types: ");
+    for (i = 0; i < cert_type_num; i++) {
+        unsigned char cert_type = p[i];
+        char *cname;
+        switch (cert_type) {
+        case TLS_CT_RSA_SIGN:
+            cname = "RSA sign";
+            break;
+
+        case TLS_CT_DSS_SIGN:
+            cname = "DSA sign";
+            break;
+
+        case TLS_CT_RSA_FIXED_DH:
+            cname = "RSA fixed DH";
+            break;
+
+        case TLS_CT_DSS_FIXED_DH:
+            cname = "DSS fixed DH";
+            break;
+
+        case TLS_CT_ECDSA_SIGN:
+            cname = "ECDSA sign";
+            break;
+
+        case TLS_CT_RSA_FIXED_ECDH:
+            cname = "RSA fixed ECDH";
+            break;
+
+        case TLS_CT_ECDSA_FIXED_ECDH:
+            cname = "ECDSA fixed ECDH";
+            break;
+
+        case TLS_CT_GOST94_SIGN:
+            cname = "GOST94 Sign";
+            break;
+
+        case TLS_CT_GOST01_SIGN:
+            cname = "GOST01 Sign";
+            break;
+
+        default:
+            cname = NULL;
+        }
+
+        if (i)
+            BIO_puts(bio, ", ");
+
+        if (cname)
+            BIO_puts(bio, cname);
+        else
+            BIO_printf(bio, "UNKNOWN (%d),", cert_type);
+    }
+    BIO_puts(bio, "\n");
+}
+
+static int do_print_sigalgs(BIO *out, SSL *s, int shared)
+{
+    int i, nsig, client;
+    client = SSL_is_server(s) ? 0 : 1;
+    if (shared)
+        nsig = SSL_get_shared_sigalgs(s, -1, NULL, NULL, NULL, NULL, NULL);
+    else
+        nsig = SSL_get_sigalgs(s, -1, NULL, NULL, NULL, NULL, NULL);
+    if (nsig == 0)
+        return 1;
+
+    if (shared)
+        BIO_puts(out, "Shared ");
+
+    if (client)
+        BIO_puts(out, "Requested ");
+    BIO_puts(out, "Signature Algorithms: ");
+    for (i = 0; i < nsig; i++) {
+        int hash_nid, sign_nid;
+        unsigned char rhash, rsign;
+        const char *sstr = NULL;
+        if (shared)
+            SSL_get_shared_sigalgs(s, i, &sign_nid, &hash_nid, NULL,
+                                   &rsign, &rhash);
+        else
+            SSL_get_sigalgs(s, i, &sign_nid, &hash_nid, NULL, &rsign, &rhash);
+        if (i)
+            BIO_puts(out, ":");
+        if (sign_nid == EVP_PKEY_RSA)
+            sstr = "RSA";
+        else if (sign_nid == EVP_PKEY_DSA)
+            sstr = "DSA";
+        else if (sign_nid == EVP_PKEY_EC)
+            sstr = "ECDSA";
+        if (sstr)
+            BIO_printf(out, "%s+", sstr);
+        else
+            BIO_printf(out, "0x%02X+", (int)rsign);
+        if (hash_nid != NID_undef)
+            BIO_printf(out, "%s", OBJ_nid2sn(hash_nid));
+        else
+            BIO_printf(out, "0x%02X", (int)rhash);
+    }
+    BIO_puts(out, "\n");
+    return 1;
+}
+
+int ssl_print_sigalgs(BIO *out, SSL *s)
+{
+    int mdnid;
+    if (!SSL_is_server(s))
+        ssl_print_client_cert_types(out, s);
+    do_print_sigalgs(out, s, 0);
+    do_print_sigalgs(out, s, 1);
+    if (SSL_get_peer_signature_nid(s, &mdnid))
+        BIO_printf(out, "Peer signing digest: %s\n", OBJ_nid2sn(mdnid));
+    return 1;
+}
+
+#ifndef OPENSSL_NO_EC
+int ssl_print_point_formats(BIO *out, SSL *s)
+{
+    int i, nformats;
+    const char *pformats;
+    nformats = SSL_get0_ec_point_formats(s, &pformats);
+    if (nformats <= 0)
+        return 1;
+    BIO_puts(out, "Supported Elliptic Curve Point Formats: ");
+    for (i = 0; i < nformats; i++, pformats++) {
+        if (i)
+            BIO_puts(out, ":");
+        switch (*pformats) {
+        case TLSEXT_ECPOINTFORMAT_uncompressed:
+            BIO_puts(out, "uncompressed");
+            break;
+
+        case TLSEXT_ECPOINTFORMAT_ansiX962_compressed_prime:
+            BIO_puts(out, "ansiX962_compressed_prime");
+            break;
+
+        case TLSEXT_ECPOINTFORMAT_ansiX962_compressed_char2:
+            BIO_puts(out, "ansiX962_compressed_char2");
+            break;
+
+        default:
+            BIO_printf(out, "unknown(%d)", (int)*pformats);
+            break;
+
+        }
+    }
+    if (nformats <= 0)
+        BIO_puts(out, "NONE");
+    BIO_puts(out, "\n");
+    return 1;
+}
+
+int ssl_print_curves(BIO *out, SSL *s, int noshared)
+{
+    int i, ncurves, *curves, nid;
+    const char *cname;
+    ncurves = SSL_get1_curves(s, NULL);
+    if (ncurves <= 0)
+        return 1;
+    curves = OPENSSL_malloc(ncurves * sizeof(int));
+    if (!curves) {
+        BIO_puts(out, "Malloc error getting supported curves\n");
+        return 0;
+    }
+    SSL_get1_curves(s, curves);
+
+
+    BIO_puts(out, "Supported Elliptic Curves: ");
+    for (i = 0; i < ncurves; i++) {
+        if (i)
+            BIO_puts(out, ":");
+        nid = curves[i];
+        /* If unrecognised print out hex version */
+        if (nid & TLSEXT_nid_unknown)
+            BIO_printf(out, "0x%04X", nid & 0xFFFF);
+        else {
+            /* Use NIST name for curve if it exists */
+            cname = EC_curve_nid2nist(nid);
+            if (!cname)
+                cname = OBJ_nid2sn(nid);
+            BIO_printf(out, "%s", cname);
+        }
+    }
+    if (ncurves == 0)
+        BIO_puts(out, "NONE");
+    OPENSSL_free(curves);
+    if (noshared) {
+        BIO_puts(out, "\n");
+        return 1;
+    }
+    BIO_puts(out, "\nShared Elliptic curves: ");
+    ncurves = SSL_get_shared_curve(s, -1);
+    for (i = 0; i < ncurves; i++) {
+        if (i)
+            BIO_puts(out, ":");
+        nid = SSL_get_shared_curve(s, i);
+        cname = EC_curve_nid2nist(nid);
+        if (!cname)
+            cname = OBJ_nid2sn(nid);
+        BIO_printf(out, "%s", cname);
+    }
+    if (ncurves == 0)
+        BIO_puts(out, "NONE");
+    BIO_puts(out, "\n");
+    return 1;
+}
+#endif
+int ssl_print_tmp_key(BIO *out, SSL *s)
+{
+    EVP_PKEY *key;
+    if (!SSL_get_server_tmp_key(s, &key))
+        return 1;
+    BIO_puts(out, "Server Temp Key: ");
+    switch (EVP_PKEY_id(key)) {
+    case EVP_PKEY_RSA:
+        BIO_printf(out, "RSA, %d bits\n", EVP_PKEY_bits(key));
+        break;
+
+    case EVP_PKEY_DH:
+        BIO_printf(out, "DH, %d bits\n", EVP_PKEY_bits(key));
+        break;
+#ifndef OPENSSL_NO_ECDH
+    case EVP_PKEY_EC:
+        {
+            EC_KEY *ec = EVP_PKEY_get1_EC_KEY(key);
+            int nid;
+            const char *cname;
+            nid = EC_GROUP_get_curve_name(EC_KEY_get0_group(ec));
+            EC_KEY_free(ec);
+            cname = EC_curve_nid2nist(nid);
+            if (!cname)
+                cname = OBJ_nid2sn(nid);
+            BIO_printf(out, "ECDH, %s, %d bits\n", cname, EVP_PKEY_bits(key));
+        }
+#endif
+    }
+    EVP_PKEY_free(key);
     return 1;
 }
 
@@ -716,6 +981,11 @@ void MS_CALLBACK tlsext_cb(SSL *s, int client_server, int type,
         extname = "next protocol";
         break;
 #endif
+#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
+    case TLSEXT_TYPE_application_layer_protocol_negotiation:
+        extname = "application layer protocol negotiation";
+        break;
+#endif
 
     case TLSEXT_TYPE_padding:
         extname = "TLS padding";
@@ -884,3 +1154,504 @@ int MS_CALLBACK verify_cookie_callback(SSL *ssl, unsigned char *cookie,
 
     return 0;
 }
+
+/*
+ * Example of extended certificate handling. Where the standard support of
+ * one certificate per algorithm is not sufficient an application can decide
+ * which certificate(s) to use at runtime based on whatever criteria it deems
+ * appropriate.
+ */
+
+/* Linked list of certificates, keys and chains */
+struct ssl_excert_st {
+    int certform;
+    const char *certfile;
+    int keyform;
+    const char *keyfile;
+    const char *chainfile;
+    X509 *cert;
+    EVP_PKEY *key;
+    STACK_OF(X509) *chain;
+    int build_chain;
+    struct ssl_excert_st *next, *prev;
+};
+
+struct chain_flags {
+    int flag;
+    const char *name;
+};
+
+struct chain_flags chain_flags_list[] = {
+    {CERT_PKEY_VALID, "Overall Validity"},
+    {CERT_PKEY_SIGN, "Sign with EE key"},
+    {CERT_PKEY_EE_SIGNATURE, "EE signature"},
+    {CERT_PKEY_CA_SIGNATURE, "CA signature"},
+    {CERT_PKEY_EE_PARAM, "EE key parameters"},
+    {CERT_PKEY_CA_PARAM, "CA key parameters"},
+    {CERT_PKEY_EXPLICIT_SIGN, "Explicity sign with EE key"},
+    {CERT_PKEY_ISSUER_NAME, "Issuer Name"},
+    {CERT_PKEY_CERT_TYPE, "Certificate Type"},
+    {0, NULL}
+};
+
+static void print_chain_flags(BIO *out, SSL *s, int flags)
+{
+    struct chain_flags *ctmp = chain_flags_list;
+    while (ctmp->name) {
+        BIO_printf(out, "\t%s: %s\n", ctmp->name,
+                   flags & ctmp->flag ? "OK" : "NOT OK");
+        ctmp++;
+    }
+    BIO_printf(out, "\tSuite B: ");
+    if (SSL_set_cert_flags(s, 0) & SSL_CERT_FLAG_SUITEB_128_LOS)
+        BIO_puts(out, flags & CERT_PKEY_SUITEB ? "OK\n" : "NOT OK\n");
+    else
+        BIO_printf(out, "not tested\n");
+}
+
+/*
+ * Very basic selection callback: just use any certificate chain reported as
+ * valid. More sophisticated could prioritise according to local policy.
+ */
+static int set_cert_cb(SSL *ssl, void *arg)
+{
+    int i, rv;
+    SSL_EXCERT *exc = arg;
+#ifdef CERT_CB_TEST_RETRY
+    static int retry_cnt;
+    if (retry_cnt < 5) {
+        retry_cnt++;
+        fprintf(stderr, "Certificate callback retry test: count %d\n",
+                retry_cnt);
+        return -1;
+    }
+#endif
+    SSL_certs_clear(ssl);
+
+    if (!exc)
+        return 1;
+
+    /*
+     * Go to end of list and traverse backwards since we prepend newer
+     * entries this retains the original order.
+     */
+    while (exc->next)
+        exc = exc->next;
+
+    i = 0;
+
+    while (exc) {
+        i++;
+        rv = SSL_check_chain(ssl, exc->cert, exc->key, exc->chain);
+        BIO_printf(bio_err, "Checking cert chain %d:\nSubject: ", i);
+        X509_NAME_print_ex(bio_err, X509_get_subject_name(exc->cert), 0,
+                           XN_FLAG_ONELINE);
+        BIO_puts(bio_err, "\n");
+
+        print_chain_flags(bio_err, ssl, rv);
+        if (rv & CERT_PKEY_VALID) {
+            SSL_use_certificate(ssl, exc->cert);
+            SSL_use_PrivateKey(ssl, exc->key);
+            /*
+             * NB: we wouldn't normally do this as it is not efficient
+             * building chains on each connection better to cache the chain
+             * in advance.
+             */
+            if (exc->build_chain) {
+                if (!SSL_build_cert_chain(ssl, 0))
+                    return 0;
+            } else if (exc->chain)
+                SSL_set1_chain(ssl, exc->chain);
+        }
+        exc = exc->prev;
+    }
+    return 1;
+}
+
+void ssl_ctx_set_excert(SSL_CTX *ctx, SSL_EXCERT *exc)
+{
+    SSL_CTX_set_cert_cb(ctx, set_cert_cb, exc);
+}
+
+static int ssl_excert_prepend(SSL_EXCERT **pexc)
+{
+    SSL_EXCERT *exc;
+    exc = OPENSSL_malloc(sizeof(SSL_EXCERT));
+    if (!exc)
+        return 0;
+    exc->certfile = NULL;
+    exc->keyfile = NULL;
+    exc->chainfile = NULL;
+    exc->cert = NULL;
+    exc->key = NULL;
+    exc->chain = NULL;
+    exc->prev = NULL;
+    exc->build_chain = 0;
+
+    exc->next = *pexc;
+    *pexc = exc;
+
+    if (exc->next) {
+        exc->certform = exc->next->certform;
+        exc->keyform = exc->next->keyform;
+        exc->next->prev = exc;
+    } else {
+        exc->certform = FORMAT_PEM;
+        exc->keyform = FORMAT_PEM;
+    }
+    return 1;
+
+}
+
+void ssl_excert_free(SSL_EXCERT *exc)
+{
+    SSL_EXCERT *curr;
+    while (exc) {
+        if (exc->cert)
+            X509_free(exc->cert);
+        if (exc->key)
+            EVP_PKEY_free(exc->key);
+        if (exc->chain)
+            sk_X509_pop_free(exc->chain, X509_free);
+        curr = exc;
+        exc = exc->next;
+        OPENSSL_free(curr);
+    }
+}
+
+int load_excert(SSL_EXCERT **pexc, BIO *err)
+{
+    SSL_EXCERT *exc = *pexc;
+    if (!exc)
+        return 1;
+    /* If nothing in list, free and set to NULL */
+    if (!exc->certfile && !exc->next) {
+        ssl_excert_free(exc);
+        *pexc = NULL;
+        return 1;
+    }
+    for (; exc; exc = exc->next) {
+        if (!exc->certfile) {
+            BIO_printf(err, "Missing filename\n");
+            return 0;
+        }
+        exc->cert = load_cert(err, exc->certfile, exc->certform,
+                              NULL, NULL, "Server Certificate");
+        if (!exc->cert)
+            return 0;
+        if (exc->keyfile) {
+            exc->key = load_key(err, exc->keyfile, exc->keyform,
+                                0, NULL, NULL, "Server Key");
+        } else {
+            exc->key = load_key(err, exc->certfile, exc->certform,
+                                0, NULL, NULL, "Server Key");
+        }
+        if (!exc->key)
+            return 0;
+        if (exc->chainfile) {
+            exc->chain = load_certs(err,
+                                    exc->chainfile, FORMAT_PEM,
+                                    NULL, NULL, "Server Chain");
+            if (!exc->chain)
+                return 0;
+        }
+    }
+    return 1;
+}
+
+int args_excert(char ***pargs, int *pargc,
+                int *badarg, BIO *err, SSL_EXCERT **pexc)
+{
+    char *arg = **pargs, *argn = (*pargs)[1];
+    SSL_EXCERT *exc = *pexc;
+    int narg = 2;
+    if (!exc) {
+        if (ssl_excert_prepend(&exc))
+            *pexc = exc;
+        else {
+            BIO_printf(err, "Error initialising xcert\n");
+            *badarg = 1;
+            goto err;
+        }
+    }
+    if (strcmp(arg, "-xcert") == 0) {
+        if (!argn) {
+            *badarg = 1;
+            return 1;
+        }
+        if (exc->certfile && !ssl_excert_prepend(&exc)) {
+            BIO_printf(err, "Error adding xcert\n");
+            *badarg = 1;
+            goto err;
+        }
+        exc->certfile = argn;
+    } else if (strcmp(arg, "-xkey") == 0) {
+        if (!argn) {
+            *badarg = 1;
+            return 1;
+        }
+        if (exc->keyfile) {
+            BIO_printf(err, "Key already specified\n");
+            *badarg = 1;
+            return 1;
+        }
+        exc->keyfile = argn;
+    } else if (strcmp(arg, "-xchain") == 0) {
+        if (!argn) {
+            *badarg = 1;
+            return 1;
+        }
+        if (exc->chainfile) {
+            BIO_printf(err, "Chain already specified\n");
+            *badarg = 1;
+            return 1;
+        }
+        exc->chainfile = argn;
+    } else if (strcmp(arg, "-xchain_build") == 0) {
+        narg = 1;
+        exc->build_chain = 1;
+    } else if (strcmp(arg, "-xcertform") == 0) {
+        if (!argn) {
+            *badarg = 1;
+            goto err;
+        }
+        exc->certform = str2fmt(argn);
+    } else if (strcmp(arg, "-xkeyform") == 0) {
+        if (!argn) {
+            *badarg = 1;
+            goto err;
+        }
+        exc->keyform = str2fmt(argn);
+    } else
+        return 0;
+
+    (*pargs) += narg;
+
+    if (pargc)
+        *pargc -= narg;
+
+    *pexc = exc;
+
+    return 1;
+
+ err:
+    ERR_print_errors(err);
+    ssl_excert_free(exc);
+    *pexc = NULL;
+    return 1;
+}
+
+static void print_raw_cipherlist(BIO *bio, SSL *s)
+{
+    const unsigned char *rlist;
+    static const unsigned char scsv_id[] = { 0, 0, 0xFF };
+    size_t i, rlistlen, num;
+    if (!SSL_is_server(s))
+        return;
+    num = SSL_get0_raw_cipherlist(s, NULL);
+    rlistlen = SSL_get0_raw_cipherlist(s, &rlist);
+    BIO_puts(bio, "Client cipher list: ");
+    for (i = 0; i < rlistlen; i += num, rlist += num) {
+        const SSL_CIPHER *c = SSL_CIPHER_find(s, rlist);
+        if (i)
+            BIO_puts(bio, ":");
+        if (c)
+            BIO_puts(bio, SSL_CIPHER_get_name(c));
+        else if (!memcmp(rlist, scsv_id - num + 3, num))
+            BIO_puts(bio, "SCSV");
+        else {
+            size_t j;
+            BIO_puts(bio, "0x");
+            for (j = 0; j < num; j++)
+                BIO_printf(bio, "%02X", rlist[j]);
+        }
+    }
+    BIO_puts(bio, "\n");
+}
+
+void print_ssl_summary(BIO *bio, SSL *s)
+{
+    const SSL_CIPHER *c;
+    X509 *peer;
+    /*
+     * const char *pnam = SSL_is_server(s) ? "client" : "server";
+     */
+    BIO_printf(bio, "Protocol version: %s\n", SSL_get_version(s));
+    print_raw_cipherlist(bio, s);
+    c = SSL_get_current_cipher(s);
+    BIO_printf(bio, "Ciphersuite: %s\n", SSL_CIPHER_get_name(c));
+    do_print_sigalgs(bio, s, 0);
+    peer = SSL_get_peer_certificate(s);
+    if (peer) {
+        int nid;
+        BIO_puts(bio, "Peer certificate: ");
+        X509_NAME_print_ex(bio, X509_get_subject_name(peer),
+                           0, XN_FLAG_ONELINE);
+        BIO_puts(bio, "\n");
+        if (SSL_get_peer_signature_nid(s, &nid))
+            BIO_printf(bio, "Hash used: %s\n", OBJ_nid2sn(nid));
+    } else
+        BIO_puts(bio, "No peer certificate\n");
+    if (peer)
+        X509_free(peer);
+#ifndef OPENSSL_NO_EC
+    ssl_print_point_formats(bio, s);
+    if (SSL_is_server(s))
+        ssl_print_curves(bio, s, 1);
+    else
+        ssl_print_tmp_key(bio, s);
+#else
+    if (!SSL_is_server(s))
+        ssl_print_tmp_key(bio, s);
+#endif
+}
+
+int args_ssl(char ***pargs, int *pargc, SSL_CONF_CTX *cctx,
+             int *badarg, BIO *err, STACK_OF(OPENSSL_STRING) **pstr)
+{
+    char *arg = **pargs, *argn = (*pargs)[1];
+    int rv;
+
+    /* Attempt to run SSL configuration command */
+    rv = SSL_CONF_cmd_argv(cctx, pargc, pargs);
+    /* If parameter not recognised just return */
+    if (rv == 0)
+        return 0;
+    /* see if missing argument error */
+    if (rv == -3) {
+        BIO_printf(err, "%s needs an argument\n", arg);
+        *badarg = 1;
+        goto end;
+    }
+    /* Check for some other error */
+    if (rv < 0) {
+        BIO_printf(err, "Error with command: \"%s %s\"\n",
+                   arg, argn ? argn : "");
+        *badarg = 1;
+        goto end;
+    }
+    /* Store command and argument */
+    /* If only one argument processed store value as NULL */
+    if (rv == 1)
+        argn = NULL;
+    if (!*pstr)
+        *pstr = sk_OPENSSL_STRING_new_null();
+    if (!*pstr || !sk_OPENSSL_STRING_push(*pstr, arg) ||
+        !sk_OPENSSL_STRING_push(*pstr, argn)) {
+        BIO_puts(err, "Memory allocation failure\n");
+        goto end;
+    }
+
+ end:
+    if (*badarg)
+        ERR_print_errors(err);
+
+    return 1;
+}
+
+int args_ssl_call(SSL_CTX *ctx, BIO *err, SSL_CONF_CTX *cctx,
+                  STACK_OF(OPENSSL_STRING) *str, int no_ecdhe, int no_jpake)
+{
+    int i;
+    SSL_CONF_CTX_set_ssl_ctx(cctx, ctx);
+    for (i = 0; i < sk_OPENSSL_STRING_num(str); i += 2) {
+        const char *param = sk_OPENSSL_STRING_value(str, i);
+        const char *value = sk_OPENSSL_STRING_value(str, i + 1);
+        /*
+         * If no_ecdhe or named curve already specified don't need a default.
+         */
+        if (!no_ecdhe && !strcmp(param, "-named_curve"))
+            no_ecdhe = 1;
+#ifndef OPENSSL_NO_JPAKE
+        if (!no_jpake && !strcmp(param, "-cipher")) {
+            BIO_puts(err, "JPAKE sets cipher to PSK\n");
+            return 0;
+        }
+#endif
+        if (SSL_CONF_cmd(cctx, param, value) <= 0) {
+            BIO_printf(err, "Error with command: \"%s %s\"\n",
+                       param, value ? value : "");
+            ERR_print_errors(err);
+            return 0;
+        }
+    }
+    /*
+     * This is a special case to keep existing s_server functionality: if we
+     * don't have any curve specified *and* we haven't disabled ECDHE then
+     * use P-256.
+     */
+    if (!no_ecdhe) {
+        if (SSL_CONF_cmd(cctx, "-named_curve", "P-256") <= 0) {
+            BIO_puts(err, "Error setting EC curve\n");
+            ERR_print_errors(err);
+            return 0;
+        }
+    }
+#ifndef OPENSSL_NO_JPAKE
+    if (!no_jpake) {
+        if (SSL_CONF_cmd(cctx, "-cipher", "PSK") <= 0) {
+            BIO_puts(err, "Error setting cipher to PSK\n");
+            ERR_print_errors(err);
+            return 0;
+        }
+    }
+#endif
+    if (!SSL_CONF_CTX_finish(cctx)) {
+        BIO_puts(err, "Error finishing context\n");
+        ERR_print_errors(err);
+        return 0;
+    }
+    return 1;
+}
+
+static int add_crls_store(X509_STORE *st, STACK_OF(X509_CRL) *crls)
+{
+    X509_CRL *crl;
+    int i;
+    for (i = 0; i < sk_X509_CRL_num(crls); i++) {
+        crl = sk_X509_CRL_value(crls, i);
+        X509_STORE_add_crl(st, crl);
+    }
+    return 1;
+}
+
+int ssl_ctx_add_crls(SSL_CTX *ctx, STACK_OF(X509_CRL) *crls, int crl_download)
+{
+    X509_STORE *st;
+    st = SSL_CTX_get_cert_store(ctx);
+    add_crls_store(st, crls);
+    if (crl_download)
+        store_setup_crl_download(st);
+    return 1;
+}
+
+int ssl_load_stores(SSL_CTX *ctx,
+                    const char *vfyCApath, const char *vfyCAfile,
+                    const char *chCApath, const char *chCAfile,
+                    STACK_OF(X509_CRL) *crls, int crl_download)
+{
+    X509_STORE *vfy = NULL, *ch = NULL;
+    int rv = 0;
+    if (vfyCApath || vfyCAfile) {
+        vfy = X509_STORE_new();
+        if (!X509_STORE_load_locations(vfy, vfyCAfile, vfyCApath))
+            goto err;
+        add_crls_store(vfy, crls);
+        SSL_CTX_set1_verify_cert_store(ctx, vfy);
+        if (crl_download)
+            store_setup_crl_download(vfy);
+    }
+    if (chCApath || chCAfile) {
+        ch = X509_STORE_new();
+        if (!X509_STORE_load_locations(ch, chCAfile, chCApath))
+            goto err;
+        SSL_CTX_set1_chain_cert_store(ctx, ch);
+    }
+    rv = 1;
+ err:
+    if (vfy)
+        X509_STORE_free(vfy);
+    if (ch)
+        X509_STORE_free(ch);
+    return rv;
+}
index 16833ac..0c1102b 100644 (file)
@@ -202,6 +202,7 @@ typedef unsigned int u_int;
 extern int verify_depth;
 extern int verify_error;
 extern int verify_return_error;
+extern int verify_quiet;
 
 #ifdef FIONBIO
 static int c_nbio = 0;
@@ -224,8 +225,10 @@ static void print_stuff(BIO *berr, SSL *con, int full);
 static int ocsp_resp_cb(SSL *s, void *arg);
 #endif
 static BIO *bio_c_out = NULL;
+static BIO *bio_c_msg = NULL;
 static int c_quiet = 0;
 static int c_ign_eof = 0;
+static int c_brief = 0;
 
 #ifndef OPENSSL_NO_PSK
 /* Default PSK identity and key */
@@ -304,6 +307,12 @@ static void sc_usage(void)
     BIO_printf(bio_err,
                " -connect host:port - who to connect to (default is %s:%s)\n",
                SSL_HOST_NAME, PORT_STR);
+    BIO_printf(bio_err,
+               " -verify_hostname host - check peer certificate matches \"host\"\n");
+    BIO_printf(bio_err,
+               " -verify_email email - check peer certificate matches \"email\"\n");
+    BIO_printf(bio_err,
+               " -verify_ip ipaddr - check peer certificate matches \"ipaddr\"\n");
 
     BIO_printf(bio_err,
                " -verify arg   - turn on peer certificate verification\n");
@@ -381,8 +390,6 @@ static void sc_usage(void)
                " -no_tls1_2/-no_tls1_1/-no_tls1/-no_ssl3/-no_ssl2 - turn off that protocol\n");
     BIO_printf(bio_err,
                " -bugs         - Switch on all SSL implementation bug workarounds\n");
-    BIO_printf(bio_err,
-               " -serverpref   - Use server's cipher preferences (only SSLv2)\n");
     BIO_printf(bio_err,
                " -cipher       - preferred cipher to use, use the 'openssl ciphers'\n");
     BIO_printf(bio_err,
@@ -413,11 +420,23 @@ static void sc_usage(void)
                " -status           - request certificate status from server\n");
     BIO_printf(bio_err,
                " -no_ticket        - disable use of RFC4507bis session tickets\n");
-# ifndef OPENSSL_NO_NEXTPROTONEG
+    BIO_printf(bio_err,
+               " -serverinfo types - send empty ClientHello extensions (comma-separated numbers)\n");
+    BIO_printf(bio_err,
+               " -curves arg       - Elliptic curves to advertise (colon-separated list)\n");
+    BIO_printf(bio_err,
+               " -sigalgs arg      - Signature algorithms to support (colon-separated list)\n");
+    BIO_printf(bio_err,
+               " -client_sigalgs arg - Signature algorithms to support for client\n");
+    BIO_printf(bio_err,
+               "                       certificate authentication (colon-separated list)\n");
+#endif
+#ifndef OPENSSL_NO_NEXTPROTONEG
     BIO_printf(bio_err,
                " -nextprotoneg arg - enable NPN extension, considering named protocols supported (comma-separated list)\n");
-# endif
 #endif
+    BIO_printf(bio_err,
+               " -alpn arg         - enable ALPN extension, considering named protocols supported (comma-separated list)\n");
     BIO_printf(bio_err,
                " -legacy_renegotiation - enable use of legacy renegotiation (dangerous)\n");
 #ifndef OPENSSL_NO_SRTP
@@ -605,6 +624,27 @@ static int next_proto_cb(SSL *s, unsigned char **out, unsigned char *outlen,
     return SSL_TLSEXT_ERR_OK;
 }
 # endif                         /* ndef OPENSSL_NO_NEXTPROTONEG */
+
+static int serverinfo_cli_parse_cb(SSL *s, unsigned int ext_type,
+                                   const unsigned char *in, size_t inlen,
+                                   int *al, void *arg)
+{
+    char pem_name[100];
+    unsigned char ext_buf[4 + 65536];
+
+    /* Reconstruct the type/len fields prior to extension data */
+    ext_buf[0] = ext_type >> 8;
+    ext_buf[1] = ext_type & 0xFF;
+    ext_buf[2] = inlen >> 8;
+    ext_buf[3] = inlen & 0xFF;
+    memcpy(ext_buf + 4, in, inlen);
+
+    BIO_snprintf(pem_name, sizeof(pem_name), "SERVERINFO FOR EXTENSION %d",
+                 ext_type);
+    PEM_write_bio(bio_c_out, pem_name, "", ext_buf, 4 + inlen);
+    return 1;
+}
+
 #endif
 
 enum {
@@ -620,7 +660,7 @@ int MAIN(int, char **);
 
 int MAIN(int argc, char **argv)
 {
-    unsigned int off = 0, clr = 0;
+    int build_chain = 0;
     SSL *con = NULL;
 #ifndef OPENSSL_NO_KRB5
     KSSL_CTX *kctx;
@@ -633,13 +673,16 @@ int MAIN(int argc, char **argv)
     short port = PORT;
     int full_log = 1;
     char *host = SSL_HOST_NAME;
-    char *cert_file = NULL, *key_file = NULL;
+    char *cert_file = NULL, *key_file = NULL, *chain_file = NULL;
     int cert_format = FORMAT_PEM, key_format = FORMAT_PEM;
     char *passarg = NULL, *pass = NULL;
     X509 *cert = NULL;
     EVP_PKEY *key = NULL;
-    char *CApath = NULL, *CAfile = NULL, *cipher = NULL;
-    int reconnect = 0, badop = 0, verify = SSL_VERIFY_NONE, bugs = 0;
+    STACK_OF(X509) *chain = NULL;
+    char *CApath = NULL, *CAfile = NULL;
+    char *chCApath = NULL, *chCAfile = NULL;
+    char *vfyCApath = NULL, *vfyCAfile = NULL;
+    int reconnect = 0, badop = 0, verify = SSL_VERIFY_NONE;
     int crlf = 0;
     int write_tty, read_tty, write_ssl, read_ssl, tty_on, ssl_pending;
     SSL_CTX *ctx = NULL;
@@ -672,6 +715,10 @@ int MAIN(int argc, char **argv)
 # ifndef OPENSSL_NO_NEXTPROTONEG
     const char *next_proto_neg_in = NULL;
 # endif
+    const char *alpn_in = NULL;
+# define MAX_SI_TYPES 100
+    unsigned short serverinfo_types[MAX_SI_TYPES];
+    int serverinfo_types_count = 0;
 #endif
     char *sess_in = NULL;
     char *sess_out = NULL;
@@ -681,13 +728,25 @@ int MAIN(int argc, char **argv)
     int enable_timeouts = 0;
     long socket_mtu = 0;
 #ifndef OPENSSL_NO_JPAKE
-    char *jpake_secret = NULL;
+    static char *jpake_secret = NULL;
+# define no_jpake !jpake_secret
+#else
+# define no_jpake 1
 #endif
 #ifndef OPENSSL_NO_SRP
     char *srppass = NULL;
     int srp_lateuser = 0;
     SRP_ARG srp_arg = { NULL, NULL, 0, 0, 0, 1024 };
 #endif
+    SSL_EXCERT *exc = NULL;
+
+    SSL_CONF_CTX *cctx = NULL;
+    STACK_OF(OPENSSL_STRING) *ssl_args = NULL;
+
+    char *crl_file = NULL;
+    int crl_format = FORMAT_PEM;
+    int crl_download = 0;
+    STACK_OF(X509_CRL) *crls = NULL;
 
     meth = SSLv23_client_method();
 
@@ -705,6 +764,12 @@ int MAIN(int argc, char **argv)
     if (!load_config(bio_err, NULL))
         goto end;
 
+    cctx = SSL_CONF_CTX_new();
+    if (!cctx)
+        goto end;
+    SSL_CONF_CTX_set_flags(cctx, SSL_CONF_FLAG_CLIENT);
+    SSL_CONF_CTX_set_flags(cctx, SSL_CONF_FLAG_CMDLINE);
+
     if (((cbuf = OPENSSL_malloc(BUFSIZZ)) == NULL) ||
         ((sbuf = OPENSSL_malloc(BUFSIZZ)) == NULL) ||
         ((mbuf = OPENSSL_malloc(BUFSIZZ)) == NULL)) {
@@ -741,12 +806,19 @@ int MAIN(int argc, char **argv)
             if (--argc < 1)
                 goto bad;
             verify_depth = atoi(*(++argv));
-            BIO_printf(bio_err, "verify depth is %d\n", verify_depth);
+            if (!c_quiet)
+                BIO_printf(bio_err, "verify depth is %d\n", verify_depth);
         } else if (strcmp(*argv, "-cert") == 0) {
             if (--argc < 1)
                 goto bad;
             cert_file = *(++argv);
-        } else if (strcmp(*argv, "-sess_out") == 0) {
+        } else if (strcmp(*argv, "-CRL") == 0) {
+            if (--argc < 1)
+                goto bad;
+            crl_file = *(++argv);
+        } else if (strcmp(*argv, "-crl_download") == 0)
+            crl_download = 1;
+        else if (strcmp(*argv, "-sess_out") == 0) {
             if (--argc < 1)
                 goto bad;
             sess_out = *(++argv);
@@ -758,13 +830,31 @@ int MAIN(int argc, char **argv)
             if (--argc < 1)
                 goto bad;
             cert_format = str2fmt(*(++argv));
+        } else if (strcmp(*argv, "-CRLform") == 0) {
+            if (--argc < 1)
+                goto bad;
+            crl_format = str2fmt(*(++argv));
         } else if (args_verify(&argv, &argc, &badarg, bio_err, &vpm)) {
             if (badarg)
                 goto bad;
             continue;
         } else if (strcmp(*argv, "-verify_return_error") == 0)
             verify_return_error = 1;
-        else if (strcmp(*argv, "-prexit") == 0)
+        else if (strcmp(*argv, "-verify_quiet") == 0)
+            verify_quiet = 1;
+        else if (strcmp(*argv, "-brief") == 0) {
+            c_brief = 1;
+            verify_quiet = 1;
+            c_quiet = 1;
+        } else if (args_excert(&argv, &argc, &badarg, bio_err, &exc)) {
+            if (badarg)
+                goto bad;
+            continue;
+        } else if (args_ssl(&argv, &argc, cctx, &badarg, bio_err, &ssl_args)) {
+            if (badarg)
+                goto bad;
+            continue;
+        } else if (strcmp(*argv, "-prexit") == 0)
             prexit = 1;
         else if (strcmp(*argv, "-crlf") == 0)
             crlf = 1;
@@ -791,6 +881,15 @@ int MAIN(int argc, char **argv)
 #endif
         else if (strcmp(*argv, "-msg") == 0)
             c_msg = 1;
+        else if (strcmp(*argv, "-msgfile") == 0) {
+            if (--argc < 1)
+                goto bad;
+            bio_c_msg = BIO_new_file(*(++argv), "w");
+        }
+#ifndef OPENSSL_NO_SSL_TRACE
+        else if (strcmp(*argv, "-trace") == 0)
+            c_msg = 2;
+#endif
         else if (strcmp(*argv, "-showcerts") == 0)
             c_showcerts = 1;
         else if (strcmp(*argv, "-nbio_test") == 0)
@@ -859,11 +958,15 @@ int MAIN(int argc, char **argv)
             meth = TLSv1_client_method();
 #endif
 #ifndef OPENSSL_NO_DTLS1
-        else if (strcmp(*argv, "-dtls1") == 0) {
+        else if (strcmp(*argv, "-dtls") == 0) {
+            meth = DTLS_client_method();
+            socket_type = SOCK_DGRAM;
+        } else if (strcmp(*argv, "-dtls1") == 0) {
             meth = DTLSv1_client_method();
             socket_type = SOCK_DGRAM;
-        } else if (strcmp(*argv, "-fallback_scsv") == 0) {
-            fallback_scsv = 1;
+        } else if (strcmp(*argv, "-dtls1_2") == 0) {
+            meth = DTLSv1_2_client_method();
+            socket_type = SOCK_DGRAM;
         } else if (strcmp(*argv, "-timeout") == 0)
             enable_timeouts = 1;
         else if (strcmp(*argv, "-mtu") == 0) {
@@ -872,9 +975,9 @@ int MAIN(int argc, char **argv)
             socket_mtu = atol(*(++argv));
         }
 #endif
-        else if (strcmp(*argv, "-bugs") == 0)
-            bugs = 1;
-        else if (strcmp(*argv, "-keyform") == 0) {
+        else if (strcmp(*argv, "-fallback_scsv") == 0) {
+            fallback_scsv = 1;
+        else if (strcmp(*argv, "-keyform") == 0) {
             if (--argc < 1)
                 goto bad;
             key_format = str2fmt(*(++argv));
@@ -882,6 +985,10 @@ int MAIN(int argc, char **argv)
             if (--argc < 1)
                 goto bad;
             passarg = *(++argv);
+        } else if (strcmp(*argv, "-cert_chain") == 0) {
+            if (--argc < 1)
+                goto bad;
+            chain_file = *(++argv);
         } else if (strcmp(*argv, "-key") == 0) {
             if (--argc < 1)
                 goto bad;
@@ -892,27 +999,30 @@ int MAIN(int argc, char **argv)
             if (--argc < 1)
                 goto bad;
             CApath = *(++argv);
-        } else if (strcmp(*argv, "-CAfile") == 0) {
+        } else if (strcmp(*argv, "-chainCApath") == 0) {
+            if (--argc < 1)
+                goto bad;
+            chCApath = *(++argv);
+        } else if (strcmp(*argv, "-verifyCApath") == 0) {
+            if (--argc < 1)
+                goto bad;
+            vfyCApath = *(++argv);
+        } else if (strcmp(*argv, "-build_chain") == 0)
+            build_chain = 1;
+        else if (strcmp(*argv, "-CAfile") == 0) {
             if (--argc < 1)
                 goto bad;
             CAfile = *(++argv);
-        } else if (strcmp(*argv, "-no_tls1_2") == 0)
-            off |= SSL_OP_NO_TLSv1_2;
-        else if (strcmp(*argv, "-no_tls1_1") == 0)
-            off |= SSL_OP_NO_TLSv1_1;
-        else if (strcmp(*argv, "-no_tls1") == 0)
-            off |= SSL_OP_NO_TLSv1;
-        else if (strcmp(*argv, "-no_ssl3") == 0)
-            off |= SSL_OP_NO_SSLv3;
-        else if (strcmp(*argv, "-no_ssl2") == 0)
-            off |= SSL_OP_NO_SSLv2;
-        else if (strcmp(*argv, "-no_comp") == 0) {
-            off |= SSL_OP_NO_COMPRESSION;
+        } else if (strcmp(*argv, "-chainCAfile") == 0) {
+            if (--argc < 1)
+                goto bad;
+            chCAfile = *(++argv);
+        } else if (strcmp(*argv, "-verifyCAfile") == 0) {
+            if (--argc < 1)
+                goto bad;
+            vfyCAfile = *(++argv);
         }
 #ifndef OPENSSL_NO_TLSEXT
-        else if (strcmp(*argv, "-no_ticket") == 0) {
-            off |= SSL_OP_NO_TICKET;
-        }
 # ifndef OPENSSL_NO_NEXTPROTONEG
         else if (strcmp(*argv, "-nextprotoneg") == 0) {
             if (--argc < 1)
@@ -920,20 +1030,32 @@ int MAIN(int argc, char **argv)
             next_proto_neg_in = *(++argv);
         }
 # endif
-#endif
-        else if (strcmp(*argv, "-serverpref") == 0)
-            off |= SSL_OP_CIPHER_SERVER_PREFERENCE;
-        else if (strcmp(*argv, "-legacy_renegotiation") == 0)
-            off |= SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION;
-        else if (strcmp(*argv, "-legacy_server_connect") == 0) {
-            off |= SSL_OP_LEGACY_SERVER_CONNECT;
-        } else if (strcmp(*argv, "-no_legacy_server_connect") == 0) {
-            clr |= SSL_OP_LEGACY_SERVER_CONNECT;
-        } else if (strcmp(*argv, "-cipher") == 0) {
+        else if (strcmp(*argv, "-alpn") == 0) {
+            if (--argc < 1)
+                goto bad;
+            alpn_in = *(++argv);
+        } else if (strcmp(*argv, "-serverinfo") == 0) {
+            char *c;
+            int start = 0;
+            int len;
+
             if (--argc < 1)
                 goto bad;
-            cipher = *(++argv);
+            c = *(++argv);
+            serverinfo_types_count = 0;
+            len = strlen(c);
+            for (i = 0; i <= len; ++i) {
+                if (i == len || c[i] == ',') {
+                    serverinfo_types[serverinfo_types_count]
+                        = atoi(c + start);
+                    serverinfo_types_count++;
+                    start = i + 1;
+                }
+                if (serverinfo_types_count == MAX_SI_TYPES)
+                    break;
+            }
         }
+#endif
 #ifdef FIONBIO
         else if (strcmp(*argv, "-nbio") == 0) {
             c_nbio = 1;
@@ -1024,11 +1146,6 @@ int MAIN(int argc, char **argv)
             goto end;
         }
         psk_identity = "JPAKE";
-        if (cipher) {
-            BIO_printf(bio_err, "JPAKE sets cipher to PSK\n");
-            goto end;
-        }
-        cipher = "PSK";
     }
 #endif
 
@@ -1087,6 +1204,33 @@ int MAIN(int argc, char **argv)
         }
     }
 
+    if (chain_file) {
+        chain = load_certs(bio_err, chain_file, FORMAT_PEM,
+                           NULL, e, "client certificate chain");
+        if (!chain)
+            goto end;
+    }
+
+    if (crl_file) {
+        X509_CRL *crl;
+        crl = load_crl(crl_file, crl_format);
+        if (!crl) {
+            BIO_puts(bio_err, "Error loading CRL\n");
+            ERR_print_errors(bio_err);
+            goto end;
+        }
+        crls = sk_X509_CRL_new_null();
+        if (!crls || !sk_X509_CRL_push(crls, crl)) {
+            BIO_puts(bio_err, "Error adding CRL\n");
+            ERR_print_errors(bio_err);
+            X509_CRL_free(crl);
+            goto end;
+        }
+    }
+
+    if (!load_excert(&exc, bio_err))
+        goto end;
+
     if (!app_RAND_load_file(NULL, bio_err, 1) && inrand == NULL
         && !RAND_status()) {
         BIO_printf(bio_err,
@@ -1097,8 +1241,10 @@ int MAIN(int argc, char **argv)
                    app_RAND_load_files(inrand));
 
     if (bio_c_out == NULL) {
-        if (c_quiet && !c_debug && !c_msg) {
+        if (c_quiet && !c_debug) {
             bio_c_out = BIO_new(BIO_s_null());
+            if (c_msg && !bio_c_msg)
+                bio_c_msg = BIO_new_fp(stdout, BIO_NOCLOSE);
         } else {
             if (bio_c_out == NULL)
                 bio_c_out = BIO_new_fp(stdout, BIO_NOCLOSE);
@@ -1120,6 +1266,17 @@ int MAIN(int argc, char **argv)
     if (vpm)
         SSL_CTX_set1_param(ctx, vpm);
 
+    if (!args_ssl_call(ctx, bio_err, cctx, ssl_args, 1, no_jpake)) {
+        ERR_print_errors(bio_err);
+        goto end;
+    }
+
+    if (!ssl_load_stores(ctx, vfyCApath, vfyCAfile, chCApath, chCAfile,
+                         crls, crl_download)) {
+        BIO_printf(bio_err, "Error loading store locations\n");
+        ERR_print_errors(bio_err);
+        goto end;
+    }
 #ifndef OPENSSL_NO_ENGINE
     if (ssl_client_engine) {
         if (!SSL_CTX_set_client_cert_engine(ctx, ssl_client_engine)) {
@@ -1149,35 +1306,43 @@ int MAIN(int argc, char **argv)
     if (srtp_profiles != NULL)
         SSL_CTX_set_tlsext_use_srtp(ctx, srtp_profiles);
 #endif
-    if (bugs)
-        SSL_CTX_set_options(ctx, SSL_OP_ALL | off);
-    else
-        SSL_CTX_set_options(ctx, off);
-
-    if (clr)
-        SSL_CTX_clear_options(ctx, clr);
+    if (exc)
+        ssl_ctx_set_excert(ctx, exc);
 
-#if !defined(OPENSSL_NO_TLSEXT) && !defined(OPENSSL_NO_NEXTPROTONEG)
+#if !defined(OPENSSL_NO_TLSEXT)
+# if !defined(OPENSSL_NO_NEXTPROTONEG)
     if (next_proto.data)
         SSL_CTX_set_next_proto_select_cb(ctx, next_proto_cb, &next_proto);
+# endif
+    if (alpn_in) {
+        unsigned short alpn_len;
+        unsigned char *alpn = next_protos_parse(&alpn_len, alpn_in);
+
+        if (alpn == NULL) {
+            BIO_printf(bio_err, "Error parsing -alpn argument\n");
+            goto end;
+        }
+        SSL_CTX_set_alpn_protos(ctx, alpn, alpn_len);
+        OPENSSL_free(alpn);
+    }
+#endif
+#ifndef OPENSSL_NO_TLSEXT
+    for (i = 0; i < serverinfo_types_count; i++) {
+        SSL_CTX_add_client_custom_ext(ctx,
+                                      serverinfo_types[i],
+                                      NULL, NULL, NULL,
+                                      serverinfo_cli_parse_cb, NULL);
+    }
 #endif
 
     if (state)
         SSL_CTX_set_info_callback(ctx, apps_ssl_info_callback);
-    if (cipher != NULL)
-        if (!SSL_CTX_set_cipher_list(ctx, cipher)) {
-            BIO_printf(bio_err, "error setting cipher list\n");
-            ERR_print_errors(bio_err);
-            goto end;
-        }
 #if 0
-        else
-            SSL_CTX_set_cipher_list(ctx, getenv("SSL_CIPHER"));
+    else
+        SSL_CTX_set_cipher_list(ctx, getenv("SSL_CIPHER"));
 #endif
 
     SSL_CTX_set_verify(ctx, verify, verify_callback);
-    if (!set_cert_key_stuff(ctx, cert, key))
-        goto end;
 
     if ((CAfile || CApath)
         && !SSL_CTX_load_verify_locations(ctx, CAfile, CApath)) {
@@ -1186,6 +1351,11 @@ int MAIN(int argc, char **argv)
     if (!SSL_CTX_set_default_verify_paths(ctx)) {
         ERR_print_errors(bio_err);
     }
+
+    ssl_ctx_add_crls(ctx, crls, crl_download);
+    if (!set_cert_key_stuff(ctx, cert, key, chain, build_chain))
+        goto end;
+
 #ifndef OPENSSL_NO_TLSEXT
     if (servername != NULL) {
         tlsextcbp.biodebug = bio_err;
@@ -1277,7 +1447,7 @@ int MAIN(int argc, char **argv)
     if (c_Pause & 0x01)
         SSL_set_debug(con, 1);
 
-    if (SSL_version(con) == DTLS1_VERSION) {
+    if (socket_type == SOCK_DGRAM) {
 
         sbio = BIO_new_dgram(s, BIO_NOCLOSE);
         if (getsockname(s, &peer, (void *)&peerlen) < 0) {
@@ -1331,8 +1501,13 @@ int MAIN(int argc, char **argv)
         BIO_set_callback_arg(sbio, (char *)bio_c_out);
     }
     if (c_msg) {
-        SSL_set_msg_callback(con, msg_cb);
-        SSL_set_msg_callback_arg(con, bio_c_out);
+#ifndef OPENSSL_NO_SSL_TRACE
+        if (c_msg == 2)
+            SSL_set_msg_callback(con, SSL_trace);
+        else
+#endif
+            SSL_set_msg_callback(con, msg_cb);
+        SSL_set_msg_callback_arg(con, bio_c_msg ? bio_c_msg : bio_c_out);
     }
 #ifndef OPENSSL_NO_TLSEXT
     if (c_tlsextdebug) {
@@ -1515,6 +1690,11 @@ int MAIN(int argc, char **argv)
                         BIO_printf(bio_err, "Error writing session file %s\n",
                                    sess_out);
                 }
+                if (c_brief) {
+                    BIO_puts(bio_err, "CONNECTION ESTABLISHED\n");
+                    print_ssl_summary(bio_err, con);
+                }
+
                 print_stuff(bio_c_out, con, full_log);
                 if (full_log > 0)
                     full_log--;
@@ -1780,7 +1960,10 @@ int MAIN(int argc, char **argv)
                 break;
             case SSL_ERROR_SYSCALL:
                 ret = get_last_socket_error();
-                BIO_printf(bio_err, "read:errno=%d\n", ret);
+                if (c_brief)
+                    BIO_puts(bio_err, "CONNECTION CLOSED BY SERVER\n");
+                else
+                    BIO_printf(bio_err, "read:errno=%d\n", ret);
                 goto shut;
             case SSL_ERROR_ZERO_RETURN:
                 BIO_printf(bio_c_out, "closed\n");
@@ -1880,8 +2063,12 @@ int MAIN(int argc, char **argv)
         SSL_CTX_free(ctx);
     if (cert)
         X509_free(cert);
+    if (crls)
+        sk_X509_CRL_pop_free(crls, X509_CRL_free);
     if (key)
         EVP_PKEY_free(key);
+    if (chain)
+        sk_X509_pop_free(chain, X509_free);
     if (pass)
         OPENSSL_free(pass);
 #ifndef OPENSSL_NO_SRP
@@ -1889,6 +2076,15 @@ int MAIN(int argc, char **argv)
 #endif
     if (vpm)
         X509_VERIFY_PARAM_free(vpm);
+    ssl_excert_free(exc);
+    if (ssl_args)
+        sk_OPENSSL_STRING_free(ssl_args);
+    if (cctx)
+        SSL_CONF_CTX_free(cctx);
+#ifndef OPENSSL_NO_JPAKE
+    if (jpake_secret && psk_key)
+        OPENSSL_free(psk_key);
+#endif
     if (cbuf != NULL) {
         OPENSSL_cleanse(cbuf, BUFSIZZ);
         OPENSSL_free(cbuf);
@@ -1905,6 +2101,10 @@ int MAIN(int argc, char **argv)
         BIO_free(bio_c_out);
         bio_c_out = NULL;
     }
+    if (bio_c_msg != NULL) {
+        BIO_free(bio_c_msg);
+        bio_c_msg = NULL;
+    }
     apps_shutdown();
     OPENSSL_EXIT(ret);
 }
@@ -1998,6 +2198,9 @@ static void print_stuff(BIO *bio, SSL *s, int full)
             BIO_write(bio, "\n", 1);
         }
 
+        ssl_print_sigalgs(bio, s);
+        ssl_print_tmp_key(bio, s);
+
         BIO_printf(bio,
                    "---\nSSL handshake has read %ld bytes and written %ld bytes\n",
                    BIO_number_read(SSL_get_rbio(s)),
@@ -2037,7 +2240,8 @@ static void print_stuff(BIO *bio, SSL *s, int full)
     }
 #endif
 
-#if !defined(OPENSSL_NO_TLSEXT) && !defined(OPENSSL_NO_NEXTPROTONEG)
+#if !defined(OPENSSL_NO_TLSEXT)
+# if !defined(OPENSSL_NO_NEXTPROTONEG)
     if (next_proto.status != -1) {
         const unsigned char *proto;
         unsigned int proto_len;
@@ -2046,6 +2250,18 @@ static void print_stuff(BIO *bio, SSL *s, int full)
         BIO_write(bio, proto, proto_len);
         BIO_write(bio, "\n", 1);
     }
+# endif
+    {
+        const unsigned char *proto;
+        unsigned int proto_len;
+        SSL_get0_alpn_selected(s, &proto, &proto_len);
+        if (proto_len > 0) {
+            BIO_printf(bio, "ALPN protocol: ");
+            BIO_write(bio, proto, proto_len);
+            BIO_write(bio, "\n", 1);
+        } else
+            BIO_printf(bio, "No ALPN negotiated\n");
+    }
 #endif
 
 #ifndef OPENSSL_NO_SRTP
index a53cadd..09c755b 100644 (file)
@@ -209,14 +209,17 @@ typedef unsigned int u_int;
 #ifndef OPENSSL_NO_RSA
 static RSA MS_CALLBACK *tmp_rsa_cb(SSL *s, int is_export, int keylength);
 #endif
-static int sv_body(char *hostname, int s, unsigned char *context);
-static int www_body(char *hostname, int s, unsigned char *context);
+static int sv_body(char *hostname, int s, int stype, unsigned char *context);
+static int www_body(char *hostname, int s, int stype, unsigned char *context);
+static int rev_body(char *hostname, int s, int stype, unsigned char *context);
 static void close_accept_socket(void);
 static void sv_usage(void);
 static int init_ssl_connection(SSL *s);
 static void print_stats(BIO *bp, SSL_CTX *ctx);
 static int generate_session_id(const SSL *ssl, unsigned char *id,
                                unsigned int *id_len);
+static void init_session_cache_ctx(SSL_CTX *sctx);
+static void free_sessions(void);
 #ifndef OPENSSL_NO_DH
 static DH *load_dh_param(const char *dhfile);
 static DH *get_dh2048(void);
@@ -286,16 +289,16 @@ static int accept_socket = -1;
 #undef PROG
 #define PROG            s_server_main
 
-extern int verify_depth, verify_return_error;
+extern int verify_depth, verify_return_error, verify_quiet;
 
-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;
+static const char *s_cert_file = TEST_CERT, *s_key_file =
+    NULL, *s_chain_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;
+static char *s_dcert_file = NULL, *s_dkey_file = NULL, *s_dchain_file = NULL;
 #ifdef FIONBIO
 static int s_nbio = 0;
 #endif
@@ -308,14 +311,18 @@ static SSL_CTX *ctx2 = NULL;
 static int www = 0;
 
 static BIO *bio_s_out = NULL;
+static BIO *bio_s_msg = 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 no_resume_ephemeral = 0;
 static int s_msg = 0;
 static int s_quiet = 0;
+static int s_ign_eof = 0;
+static int s_brief = 0;
 
 static char *keymatexportlabel = NULL;
 static int keymatexportlen = 20;
@@ -332,6 +339,12 @@ static long socket_mtu;
 static int cert_chain = 0;
 #endif
 
+#ifndef OPENSSL_NO_TLSEXT
+static BIO *serverinfo_in = NULL;
+static const char *s_serverinfo_file = NULL;
+
+#endif
+
 #ifndef OPENSSL_NO_PSK
 static char *psk_identity = "Client_identity";
 char *psk_key = NULL;           /* by default PSK is not used */
@@ -453,12 +466,13 @@ err:
 static void s_server_init(void)
 {
     accept_socket = -1;
-    cipher = NULL;
     s_server_verify = SSL_VERIFY_NONE;
     s_dcert_file = NULL;
     s_dkey_file = NULL;
+    s_dchain_file = NULL;
     s_cert_file = TEST_CERT;
     s_key_file = NULL;
+    s_chain_file = NULL;
 # ifndef OPENSSL_NO_TLSEXT
     s_cert_file2 = TEST_CERT2;
     s_key_file2 = NULL;
@@ -475,6 +489,7 @@ static void s_server_init(void)
     s_debug = 0;
     s_msg = 0;
     s_quiet = 0;
+    s_brief = 0;
     hack = 0;
 # ifndef OPENSSL_NO_ENGINE
     engine_id = NULL;
@@ -488,6 +503,12 @@ static void sv_usage(void)
     BIO_printf(bio_err, "\n");
     BIO_printf(bio_err,
                " -accept arg   - port to accept on (default is %d)\n", PORT);
+    BIO_printf(bio_err,
+               " -verify_hostname host - check peer certificate matches \"host\"\n");
+    BIO_printf(bio_err,
+               " -verify_email email - check peer certificate matches \"email\"\n");
+    BIO_printf(bio_err,
+               " -verify_ip ipaddr - check peer certificate matches \"ipaddr\"\n");
     BIO_printf(bio_err, " -context arg  - set session ID context\n");
     BIO_printf(bio_err,
                " -verify arg   - turn on peer certificate verification\n");
@@ -497,6 +518,16 @@ static void sv_usage(void)
                " -verify_return_error - return verification errors\n");
     BIO_printf(bio_err, " -cert arg     - certificate file to use\n");
     BIO_printf(bio_err, "                 (default is %s)\n", TEST_CERT);
+#ifndef OPENSSL_NO_TLSEXT
+    BIO_printf(bio_err,
+               " -serverinfo arg - PEM serverinfo file for certificate\n");
+    BIO_printf(bio_err,
+               " -auth               - send and receive RFC 5878 TLS auth extensions and supplemental data\n");
+    BIO_printf(bio_err,
+               " -auth_require_reneg - Do not send TLS auth extensions until renegotiation\n");
+#endif
+    BIO_printf(bio_err,
+               " -no_resumption_on_reneg - set SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION flag\n");
     BIO_printf(bio_err,
                " -crl_check    - check the peer certificate has not been revoked by its CA.\n"
                "                 The CRL(s) are appended to the certificate file\n");
@@ -575,6 +606,7 @@ static void sv_usage(void)
     BIO_printf(bio_err, " -tls1_1       - Just talk TLSv1.1\n");
     BIO_printf(bio_err, " -tls1         - Just talk TLSv1\n");
     BIO_printf(bio_err, " -dtls1        - Just talk DTLSv1\n");
+    BIO_printf(bio_err, " -dtls1_2      - Just talk DTLSv1.2\n");
     BIO_printf(bio_err, " -timeout      - Enable timeouts\n");
     BIO_printf(bio_err, " -mtu          - Set link layer MTU\n");
     BIO_printf(bio_err, " -chain        - Read a certificate chain\n");
@@ -626,6 +658,12 @@ static void sv_usage(void)
                " -no_ticket    - disable use of RFC4507bis session tickets\n");
     BIO_printf(bio_err,
                " -legacy_renegotiation - enable use of legacy renegotiation (dangerous)\n");
+    BIO_printf(bio_err,
+               " -sigalgs arg      - Signature algorithms to support (colon-separated list)\n");
+    BIO_printf(bio_err,
+               " -client_sigalgs arg  - Signature algorithms to support for client \n");
+    BIO_printf(bio_err,
+               "                        certificate authentication (colon-separated list)\n");
 # ifndef OPENSSL_NO_NEXTPROTONEG
     BIO_printf(bio_err,
                " -nextprotoneg arg - set the advertised protocols for the NPN extension (comma-separated list)\n");
@@ -634,6 +672,8 @@ static void sv_usage(void)
     BIO_printf(bio_err,
                " -use_srtp profiles - Offer SRTP key management with a colon-separated profile list\n");
 # endif
+    BIO_printf(bio_err,
+               " -alpn arg  - set the advertised protocols for the ALPN extension (comma-separated list)\n");
 #endif
     BIO_printf(bio_err,
                " -keymatexport label   - Export keying material using label\n");
@@ -994,12 +1034,53 @@ static int next_proto_cb(SSL *s, const unsigned char **data,
 }
 # endif                         /* ndef OPENSSL_NO_NEXTPROTONEG */
 
-#endif
+/* This the context that we pass to alpn_cb */
+typedef struct tlsextalpnctx_st {
+    unsigned char *data;
+    unsigned short len;
+} tlsextalpnctx;
+
+static int alpn_cb(SSL *s, const unsigned char **out, unsigned char *outlen,
+                   const unsigned char *in, unsigned int inlen, void *arg)
+{
+    tlsextalpnctx *alpn_ctx = arg;
+
+    if (!s_quiet) {
+        /* We can assume that |in| is syntactically valid. */
+        unsigned i;
+        BIO_printf(bio_s_out, "ALPN protocols advertised by the client: ");
+        for (i = 0; i < inlen;) {
+            if (i)
+                BIO_write(bio_s_out, ", ", 2);
+            BIO_write(bio_s_out, &in[i + 1], in[i]);
+            i += in[i] + 1;
+        }
+        BIO_write(bio_s_out, "\n", 1);
+    }
+
+    if (SSL_select_next_proto
+        ((unsigned char **)out, outlen, alpn_ctx->data, alpn_ctx->len, in,
+         inlen) != OPENSSL_NPN_NEGOTIATED) {
+        return SSL_TLSEXT_ERR_NOACK;
+    }
+
+    if (!s_quiet) {
+        BIO_printf(bio_s_out, "ALPN protocols selected: ");
+        BIO_write(bio_s_out, *out, *outlen);
+        BIO_write(bio_s_out, "\n", 1);
+    }
+
+    return SSL_TLSEXT_ERR_OK;
+}
+#endif                          /* ndef OPENSSL_NO_TLSEXT */
 
 int MAIN(int, char **);
 
 #ifndef OPENSSL_NO_JPAKE
 static char *jpake_secret = NULL;
+# define no_jpake !jpake_secret
+#else
+# define no_jpake 1
 #endif
 #ifndef OPENSSL_NO_SRP
 static srpsrvparm srp_callback_parm;
@@ -1014,18 +1095,14 @@ int MAIN(int argc, char *argv[])
     int badarg = 0;
     short port = PORT;
     char *CApath = NULL, *CAfile = NULL;
+    char *chCApath = NULL, *chCAfile = NULL;
+    char *vfyCApath = NULL, *vfyCAfile = NULL;
     unsigned char *context = NULL;
     char *dhfile = NULL;
-#ifndef OPENSSL_NO_ECDH
-    char *named_curve = NULL;
-#endif
-    int badop = 0, bugs = 0;
+    int badop = 0;
     int ret = 1;
-    int off = 0;
-    int no_tmp_rsa = 0, no_dhe = 0, nocert = 0;
-#ifndef OPENSSL_NO_ECDH
-    int no_ecdhe = 0;
-#endif
+    int build_chain = 0;
+    int no_tmp_rsa = 0, no_dhe = 0, no_ecdhe = 0, nocert = 0;
     int state = 0;
     const SSL_METHOD *meth = NULL;
     int socket_type = SOCK_STREAM;
@@ -1036,16 +1113,20 @@ int MAIN(int argc, char *argv[])
     char *dpassarg = NULL, *dpass = NULL;
     int s_dcert_format = FORMAT_PEM, s_dkey_format = FORMAT_PEM;
     X509 *s_cert = NULL, *s_dcert = NULL;
+    STACK_OF(X509) *s_chain = NULL, *s_dchain = NULL;
     EVP_PKEY *s_key = NULL, *s_dkey = NULL;
-    int no_cache = 0;
+    int no_cache = 0, ext_cache = 0;
+    int rev = 0, naccept = -1;
 #ifndef OPENSSL_NO_TLSEXT
     EVP_PKEY *s_key2 = NULL;
     X509 *s_cert2 = NULL;
     tlsextctx tlsextcbp = { NULL, NULL, SSL_TLSEXT_ERR_ALERT_WARNING };
 # ifndef OPENSSL_NO_NEXTPROTONEG
     const char *next_proto_neg_in = NULL;
-    tlsextnextprotoctx next_proto;
+    tlsextnextprotoctx next_proto = { NULL, 0 };
 # endif
+    const char *alpn_in = NULL;
+    tlsextalpnctx alpn_ctx = { NULL, 0 };
 #endif
 #ifndef OPENSSL_NO_PSK
     /* by default do not send a PSK identity hint */
@@ -1055,6 +1136,15 @@ int MAIN(int argc, char *argv[])
     char *srpuserseed = NULL;
     char *srp_verifier_file = NULL;
 #endif
+    SSL_EXCERT *exc = NULL;
+    SSL_CONF_CTX *cctx = NULL;
+    STACK_OF(OPENSSL_STRING) *ssl_args = NULL;
+
+    char *crl_file = NULL;
+    int crl_format = FORMAT_PEM;
+    int crl_download = 0;
+    STACK_OF(X509_CRL) *crls = NULL;
+
     meth = SSLv23_server_method();
 
     local_argc = argc;
@@ -1071,6 +1161,12 @@ int MAIN(int argc, char *argv[])
     if (!load_config(bio_err, NULL))
         goto end;
 
+    cctx = SSL_CONF_CTX_new();
+    if (!cctx)
+        goto end;
+    SSL_CONF_CTX_set_flags(cctx, SSL_CONF_FLAG_SERVER);
+    SSL_CONF_CTX_set_flags(cctx, SSL_CONF_FLAG_CMDLINE);
+
     verify_depth = 0;
 #ifdef FIONBIO
     s_nbio = 0;
@@ -1086,12 +1182,21 @@ int MAIN(int argc, char *argv[])
                 goto bad;
             if (!extract_port(*(++argv), &port))
                 goto bad;
+        } else if (strcmp(*argv, "-naccept") == 0) {
+            if (--argc < 1)
+                goto bad;
+            naccept = atol(*(++argv));
+            if (naccept <= 0) {
+                BIO_printf(bio_err, "bad accept value %s\n", *argv);
+                goto bad;
+            }
         } else if (strcmp(*argv, "-verify") == 0) {
             s_server_verify = SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE;
             if (--argc < 1)
                 goto bad;
             verify_depth = atoi(*(++argv));
-            BIO_printf(bio_err, "verify depth is %d\n", verify_depth);
+            if (!s_quiet)
+                BIO_printf(bio_err, "verify depth is %d\n", verify_depth);
         } else if (strcmp(*argv, "-Verify") == 0) {
             s_server_verify =
                 SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT |
@@ -1099,9 +1204,10 @@ int MAIN(int argc, char *argv[])
             if (--argc < 1)
                 goto bad;
             verify_depth = atoi(*(++argv));
-            BIO_printf(bio_err,
-                       "verify depth is %d, must return a certificate\n",
-                       verify_depth);
+            if (!s_quiet)
+                BIO_printf(bio_err,
+                           "verify depth is %d, must return a certificate\n",
+                           verify_depth);
         } else if (strcmp(*argv, "-context") == 0) {
             if (--argc < 1)
                 goto bad;
@@ -1110,7 +1216,20 @@ int MAIN(int argc, char *argv[])
             if (--argc < 1)
                 goto bad;
             s_cert_file = *(++argv);
-        } else if (strcmp(*argv, "-certform") == 0) {
+        } else if (strcmp(*argv, "-CRL") == 0) {
+            if (--argc < 1)
+                goto bad;
+            crl_file = *(++argv);
+        } else if (strcmp(*argv, "-crl_download") == 0)
+            crl_download = 1;
+#ifndef OPENSSL_NO_TLSEXT
+        else if (strcmp(*argv, "-serverinfo") == 0) {
+            if (--argc < 1)
+                goto bad;
+            s_serverinfo_file = *(++argv);
+        }
+#endif
+        else if (strcmp(*argv, "-certform") == 0) {
             if (--argc < 1)
                 goto bad;
             s_cert_format = str2fmt(*(++argv));
@@ -1126,19 +1245,15 @@ int MAIN(int argc, char *argv[])
             if (--argc < 1)
                 goto bad;
             passarg = *(++argv);
-        } else if (strcmp(*argv, "-dhparam") == 0) {
+        } else if (strcmp(*argv, "-cert_chain") == 0) {
             if (--argc < 1)
                 goto bad;
-            dhfile = *(++argv);
-        }
-#ifndef OPENSSL_NO_ECDH
-        else if (strcmp(*argv, "-named_curve") == 0) {
+            s_chain_file = *(++argv);
+        } else if (strcmp(*argv, "-dhparam") == 0) {
             if (--argc < 1)
                 goto bad;
-            named_curve = *(++argv);
-        }
-#endif
-        else if (strcmp(*argv, "-dcertform") == 0) {
+            dhfile = *(++argv);
+        } else if (strcmp(*argv, "-dcertform") == 0) {
             if (--argc < 1)
                 goto bad;
             s_dcert_format = str2fmt(*(++argv));
@@ -1158,32 +1273,62 @@ int MAIN(int argc, char *argv[])
             if (--argc < 1)
                 goto bad;
             s_dkey_file = *(++argv);
+        } else if (strcmp(*argv, "-dcert_chain") == 0) {
+            if (--argc < 1)
+                goto bad;
+            s_dchain_file = *(++argv);
         } else if (strcmp(*argv, "-nocert") == 0) {
             nocert = 1;
         } else if (strcmp(*argv, "-CApath") == 0) {
             if (--argc < 1)
                 goto bad;
             CApath = *(++argv);
+        } else if (strcmp(*argv, "-chainCApath") == 0) {
+            if (--argc < 1)
+                goto bad;
+            chCApath = *(++argv);
+        } else if (strcmp(*argv, "-verifyCApath") == 0) {
+            if (--argc < 1)
+                goto bad;
+            vfyCApath = *(++argv);
         } else if (strcmp(*argv, "-no_cache") == 0)
             no_cache = 1;
-        else if (args_verify(&argv, &argc, &badarg, bio_err, &vpm)) {
+        else if (strcmp(*argv, "-ext_cache") == 0)
+            ext_cache = 1;
+        else if (strcmp(*argv, "-CRLform") == 0) {
+            if (--argc < 1)
+                goto bad;
+            crl_format = str2fmt(*(++argv));
+        } else if (args_verify(&argv, &argc, &badarg, bio_err, &vpm)) {
+            if (badarg)
+                goto bad;
+            continue;
+        } else if (args_excert(&argv, &argc, &badarg, bio_err, &exc)) {
+            if (badarg)
+                goto bad;
+            continue;
+        } else if (args_ssl(&argv, &argc, cctx, &badarg, bio_err, &ssl_args)) {
             if (badarg)
                 goto bad;
             continue;
         } else if (strcmp(*argv, "-verify_return_error") == 0)
             verify_return_error = 1;
-        else if (strcmp(*argv, "-serverpref") == 0) {
-            off |= SSL_OP_CIPHER_SERVER_PREFERENCE;
-        } else if (strcmp(*argv, "-legacy_renegotiation") == 0)
-            off |= SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION;
-        else if (strcmp(*argv, "-cipher") == 0) {
+        else if (strcmp(*argv, "-verify_quiet") == 0)
+            verify_quiet = 1;
+        else if (strcmp(*argv, "-build_chain") == 0)
+            build_chain = 1;
+        else if (strcmp(*argv, "-CAfile") == 0) {
             if (--argc < 1)
                 goto bad;
-            cipher = *(++argv);
-        } else if (strcmp(*argv, "-CAfile") == 0) {
+            CAfile = *(++argv);
+        } else if (strcmp(*argv, "-chainCAfile") == 0) {
             if (--argc < 1)
                 goto bad;
-            CAfile = *(++argv);
+            chCAfile = *(++argv);
+        } else if (strcmp(*argv, "-verifyCAfile") == 0) {
+            if (--argc < 1)
+                goto bad;
+            vfyCAfile = *(++argv);
         }
 #ifdef FIONBIO
         else if (strcmp(*argv, "-nbio") == 0) {
@@ -1195,7 +1340,11 @@ int MAIN(int argc, char *argv[])
             s_nbio = 1;
 #endif
             s_nbio_test = 1;
-        } else if (strcmp(*argv, "-debug") == 0) {
+        } else if (strcmp(*argv, "-ign_eof") == 0)
+            s_ign_eof = 1;
+        else if (strcmp(*argv, "-no_ign_eof") == 0)
+            s_ign_eof = 0;
+        else if (strcmp(*argv, "-debug") == 0) {
             s_debug = 1;
         }
 #ifndef OPENSSL_NO_TLSEXT
@@ -1226,7 +1375,17 @@ int MAIN(int argc, char *argv[])
 #endif
         else if (strcmp(*argv, "-msg") == 0) {
             s_msg = 1;
-        } else if (strcmp(*argv, "-hack") == 0) {
+        } else if (strcmp(*argv, "-msgfile") == 0) {
+            if (--argc < 1)
+                goto bad;
+            bio_s_msg = BIO_new_file(*(++argv), "w");
+        }
+#ifndef OPENSSL_NO_SSL_TRACE
+        else if (strcmp(*argv, "-trace") == 0) {
+            s_msg = 2;
+        }
+#endif
+        else if (strcmp(*argv, "-hack") == 0) {
             hack = 1;
         } else if (strcmp(*argv, "-state") == 0) {
             state = 1;
@@ -1234,18 +1393,19 @@ int MAIN(int argc, char *argv[])
             s_crlf = 1;
         } else if (strcmp(*argv, "-quiet") == 0) {
             s_quiet = 1;
-        } else if (strcmp(*argv, "-bugs") == 0) {
-            bugs = 1;
+        } else if (strcmp(*argv, "-brief") == 0) {
+            s_quiet = 1;
+            s_brief = 1;
+            verify_quiet = 1;
         } else if (strcmp(*argv, "-no_tmp_rsa") == 0) {
             no_tmp_rsa = 1;
         } else if (strcmp(*argv, "-no_dhe") == 0) {
             no_dhe = 1;
-        }
-#ifndef OPENSSL_NO_ECDH
-        else if (strcmp(*argv, "-no_ecdhe") == 0) {
+        } else if (strcmp(*argv, "-no_ecdhe") == 0) {
             no_ecdhe = 1;
+        } else if (strcmp(*argv, "-no_resume_ephemeral") == 0) {
+            no_resume_ephemeral = 1;
         }
-#endif
 #ifndef OPENSSL_NO_PSK
         else if (strcmp(*argv, "-psk_hint") == 0) {
             if (--argc < 1)
@@ -1278,32 +1438,18 @@ int MAIN(int argc, char *argv[])
             meth = TLSv1_server_method();
         }
 #endif
-        else if (strcmp(*argv, "-www") == 0) {
+        else if (strcmp(*argv, "-rev") == 0) {
+            rev = 1;
+        } else if (strcmp(*argv, "-www") == 0) {
             www = 1;
         } else if (strcmp(*argv, "-WWW") == 0) {
             www = 2;
         } else if (strcmp(*argv, "-HTTP") == 0) {
             www = 3;
-        } else if (strcmp(*argv, "-no_ssl2") == 0) {
-            off |= SSL_OP_NO_SSLv2;
-        } else if (strcmp(*argv, "-no_ssl3") == 0) {
-            off |= SSL_OP_NO_SSLv3;
-        } else if (strcmp(*argv, "-no_tls1") == 0) {
-            off |= SSL_OP_NO_TLSv1;
-        } else if (strcmp(*argv, "-no_tls1_1") == 0) {
-            off |= SSL_OP_NO_TLSv1_1;
-        } else if (strcmp(*argv, "-no_tls1_2") == 0) {
-            off |= SSL_OP_NO_TLSv1_2;
-        } else if (strcmp(*argv, "-no_comp") == 0) {
-            off |= SSL_OP_NO_COMPRESSION;
-        }
-#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) {
+            no_ecdhe = 1;
             meth = SSLv2_server_method();
         }
 #endif
@@ -1322,9 +1468,15 @@ int MAIN(int argc, char *argv[])
         }
 #endif
 #ifndef OPENSSL_NO_DTLS1
-        else if (strcmp(*argv, "-dtls1") == 0) {
+        else if (strcmp(*argv, "-dtls") == 0) {
+            meth = DTLS_server_method();
+            socket_type = SOCK_DGRAM;
+        } else if (strcmp(*argv, "-dtls1") == 0) {
             meth = DTLSv1_server_method();
             socket_type = SOCK_DGRAM;
+        } else if (strcmp(*argv, "-dtls1_2") == 0) {
+            meth = DTLSv1_2_server_method();
+            socket_type = SOCK_DGRAM;
         } else if (strcmp(*argv, "-timeout") == 0)
             enable_timeouts = 1;
         else if (strcmp(*argv, "-mtu") == 0) {
@@ -1374,6 +1526,11 @@ int MAIN(int argc, char *argv[])
             next_proto_neg_in = *(++argv);
         }
 # endif
+        else if (strcmp(*argv, "-alpn") == 0) {
+            if (--argc < 1)
+                goto bad;
+            alpn_in = *(++argv);
+        }
 #endif
 #if !defined(OPENSSL_NO_JPAKE) && !defined(OPENSSL_NO_PSK)
         else if (strcmp(*argv, "-jpake") == 0) {
@@ -1426,11 +1583,6 @@ int MAIN(int argc, char *argv[])
             goto end;
         }
         psk_identity = "JPAKE";
-        if (cipher) {
-            BIO_printf(bio_err, "JPAKE sets cipher to PSK\n");
-            goto end;
-        }
-        cipher = "PSK";
     }
 #endif
 
@@ -1453,6 +1605,9 @@ int MAIN(int argc, char *argv[])
         s_key_file2 = s_cert_file2;
 #endif
 
+    if (!load_excert(&exc, bio_err))
+        goto end;
+
     if (nocert == 0) {
         s_key = load_key(bio_err, s_key_file, s_key_format, 0, pass, e,
                          "server certificate private key file");
@@ -1468,6 +1623,12 @@ int MAIN(int argc, char *argv[])
             ERR_print_errors(bio_err);
             goto end;
         }
+        if (s_chain_file) {
+            s_chain = load_certs(bio_err, s_chain_file, FORMAT_PEM,
+                                 NULL, e, "server certificate chain");
+            if (!s_chain)
+                goto end;
+        }
 #ifndef OPENSSL_NO_TLSEXT
         if (tlsextcbp.servername) {
             s_key2 = load_key(bio_err, s_key_file2, s_key_format, 0, pass, e,
@@ -1485,9 +1646,10 @@ int MAIN(int argc, char *argv[])
                 goto end;
             }
         }
-#endif
+#endif                          /* OPENSSL_NO_TLSEXT */
     }
-#if !defined(OPENSSL_NO_TLSEXT) && !defined(OPENSSL_NO_NEXTPROTONEG)
+#if !defined(OPENSSL_NO_TLSEXT)
+# if !defined(OPENSSL_NO_NEXTPROTONEG)
     if (next_proto_neg_in) {
         unsigned short len;
         next_proto.data = next_protos_parse(&len, next_proto_neg_in);
@@ -1497,8 +1659,34 @@ int MAIN(int argc, char *argv[])
     } else {
         next_proto.data = NULL;
     }
+# endif
+    alpn_ctx.data = NULL;
+    if (alpn_in) {
+        unsigned short len;
+        alpn_ctx.data = next_protos_parse(&len, alpn_in);
+        if (alpn_ctx.data == NULL)
+            goto end;
+        alpn_ctx.len = len;
+    }
 #endif
 
+    if (crl_file) {
+        X509_CRL *crl;
+        crl = load_crl(crl_file, crl_format);
+        if (!crl) {
+            BIO_puts(bio_err, "Error loading CRL\n");
+            ERR_print_errors(bio_err);
+            goto end;
+        }
+        crls = sk_X509_CRL_new_null();
+        if (!crls || !sk_X509_CRL_push(crls, crl)) {
+            BIO_puts(bio_err, "Error adding CRL\n");
+            ERR_print_errors(bio_err);
+            X509_CRL_free(crl);
+            goto end;
+        }
+    }
+
     if (s_dcert_file) {
 
         if (s_dkey_file == NULL)
@@ -1518,6 +1706,12 @@ int MAIN(int argc, char *argv[])
             ERR_print_errors(bio_err);
             goto end;
         }
+        if (s_dchain_file) {
+            s_dchain = load_certs(bio_err, s_dchain_file, FORMAT_PEM,
+                                  NULL, e, "second server certificate chain");
+            if (!s_dchain)
+                goto end;
+        }
 
     }
 
@@ -1531,8 +1725,10 @@ int MAIN(int argc, char *argv[])
                    app_RAND_load_files(inrand));
 
     if (bio_s_out == NULL) {
-        if (s_quiet && !s_debug && !s_msg) {
+        if (s_quiet && !s_debug) {
             bio_s_out = BIO_new(BIO_s_null());
+            if (s_msg && !bio_s_msg)
+                bio_s_msg = BIO_new_fp(stdout, BIO_NOCLOSE);
         } else {
             if (bio_s_out == NULL)
                 bio_s_out = BIO_new_fp(stdout, BIO_NOCLOSE);
@@ -1572,16 +1768,17 @@ int MAIN(int argc, char *argv[])
         BIO_printf(bio_err, "id_prefix '%s' set.\n", session_id_prefix);
     }
     SSL_CTX_set_quiet_shutdown(ctx, 1);
-    if (bugs)
-        SSL_CTX_set_options(ctx, SSL_OP_ALL);
     if (hack)
         SSL_CTX_set_options(ctx, SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG);
-    SSL_CTX_set_options(ctx, off);
+    if (exc)
+        ssl_ctx_set_excert(ctx, exc);
 
     if (state)
         SSL_CTX_set_info_callback(ctx, apps_ssl_info_callback);
     if (no_cache)
         SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_OFF);
+    else if (ext_cache)
+        init_session_cache_ctx(ctx);
     else
         SSL_CTX_sess_set_cache_size(ctx, 128);
 
@@ -1612,6 +1809,17 @@ int MAIN(int argc, char *argv[])
     if (vpm)
         SSL_CTX_set1_param(ctx, vpm);
 
+    ssl_ctx_add_crls(ctx, crls, 0);
+
+    if (!args_ssl_call(ctx, bio_err, cctx, ssl_args, no_ecdhe, no_jpake))
+        goto end;
+
+    if (!ssl_load_stores(ctx, vfyCApath, vfyCAfile, chCApath, chCAfile,
+                         crls, crl_download)) {
+        BIO_printf(bio_err, "Error loading store locations\n");
+        ERR_print_errors(bio_err);
+        goto end;
+    }
 #ifndef OPENSSL_NO_TLSEXT
     if (s_cert2) {
         ctx2 = SSL_CTX_new(meth);
@@ -1639,17 +1847,18 @@ int MAIN(int argc, char *argv[])
             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);
+        if (exc)
+            ssl_ctx_set_excert(ctx2, exc);
 
         if (state)
             SSL_CTX_set_info_callback(ctx2, apps_ssl_info_callback);
 
         if (no_cache)
             SSL_CTX_set_session_cache_mode(ctx2, SSL_SESS_CACHE_OFF);
+        else if (ext_cache)
+            init_session_cache_ctx(ctx2);
         else
             SSL_CTX_sess_set_cache_size(ctx2, 128);
 
@@ -1659,12 +1868,20 @@ int MAIN(int argc, char *argv[])
         }
         if (vpm)
             SSL_CTX_set1_param(ctx2, vpm);
+
+        ssl_ctx_add_crls(ctx2, crls, 0);
+
+        if (!args_ssl_call(ctx2, bio_err, cctx, ssl_args, no_ecdhe, no_jpake))
+            goto end;
+
     }
 # ifndef OPENSSL_NO_NEXTPROTONEG
     if (next_proto.data)
         SSL_CTX_set_next_protos_advertised_cb(ctx, next_proto_cb,
                                               &next_proto);
 # endif
+    if (alpn_ctx.data)
+        SSL_CTX_set_alpn_select_cb(ctx, alpn_cb, &alpn_ctx);
 #endif
 
 #ifndef OPENSSL_NO_DH
@@ -1708,54 +1925,21 @@ int MAIN(int argc, char *argv[])
     }
 #endif
 
-#ifndef OPENSSL_NO_ECDH
-    if (!no_ecdhe) {
-        EC_KEY *ecdh = NULL;
-
-        if (named_curve) {
-            int nid = OBJ_sn2nid(named_curve);
-
-            if (nid == 0) {
-                BIO_printf(bio_err, "unknown curve name (%s)\n", named_curve);
-                goto end;
-            }
-            ecdh = EC_KEY_new_by_curve_name(nid);
-            if (ecdh == NULL) {
-                BIO_printf(bio_err, "unable to create curve (%s)\n",
-                           named_curve);
-                goto end;
-            }
-        }
-
-        if (ecdh != NULL) {
-            BIO_printf(bio_s_out, "Setting temp ECDH parameters\n");
-        } else {
-            BIO_printf(bio_s_out, "Using default temp ECDH parameters\n");
-            ecdh = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
-            if (ecdh == NULL) {
-                BIO_printf(bio_err, "unable to create curve (nistp256)\n");
-                goto end;
-            }
-        }
-        (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);
+    if (!set_cert_key_stuff(ctx, s_cert, s_key, s_chain, build_chain))
+        goto end;
+#ifndef OPENSSL_NO_TLSEXT
+    if (s_serverinfo_file != NULL
+        && !SSL_CTX_use_serverinfo_file(ctx, s_serverinfo_file)) {
+        ERR_print_errors(bio_err);
+        goto end;
     }
 #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))
+    if (ctx2 && !set_cert_key_stuff(ctx2, s_cert2, s_key2, NULL, build_chain))
         goto end;
 #endif
     if (s_dcert != NULL) {
-        if (!set_cert_key_stuff(ctx, s_dcert, s_dkey))
+        if (!set_cert_key_stuff(ctx, s_dcert, s_dkey, s_dchain, build_chain))
             goto end;
     }
 #ifndef OPENSSL_NO_RSA
@@ -1814,20 +1998,6 @@ int MAIN(int argc, char *argv[])
     }
 #endif
 
-    if (cipher != NULL) {
-        if (!SSL_CTX_set_cipher_list(ctx, cipher)) {
-            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);
@@ -1879,10 +2049,15 @@ int MAIN(int argc, char *argv[])
 
     BIO_printf(bio_s_out, "ACCEPT\n");
     (void)BIO_flush(bio_s_out);
-    if (www)
-        do_server(port, socket_type, &accept_socket, www_body, context);
+    if (rev)
+        do_server(port, socket_type, &accept_socket, rev_body, context,
+                  naccept);
+    else if (www)
+        do_server(port, socket_type, &accept_socket, www_body, context,
+                  naccept);
     else
-        do_server(port, socket_type, &accept_socket, sv_body, context);
+        do_server(port, socket_type, &accept_socket, sv_body, context,
+                  naccept);
     print_stats(bio_s_out, ctx);
     ret = 0;
  end:
@@ -1890,18 +2065,25 @@ int MAIN(int argc, char *argv[])
         SSL_CTX_free(ctx);
     if (s_cert)
         X509_free(s_cert);
+    if (crls)
+        sk_X509_CRL_pop_free(crls, X509_CRL_free);
     if (s_dcert)
         X509_free(s_dcert);
     if (s_key)
         EVP_PKEY_free(s_key);
     if (s_dkey)
         EVP_PKEY_free(s_dkey);
+    if (s_chain)
+        sk_X509_pop_free(s_chain, X509_free);
+    if (s_dchain)
+        sk_X509_pop_free(s_dchain, X509_free);
     if (pass)
         OPENSSL_free(pass);
     if (dpass)
         OPENSSL_free(dpass);
     if (vpm)
         X509_VERIFY_PARAM_free(vpm);
+    free_sessions();
 #ifndef OPENSSL_NO_TLSEXT
     if (tlscstatp.host)
         OPENSSL_free(tlscstatp.host);
@@ -1915,11 +2097,32 @@ int MAIN(int argc, char *argv[])
         X509_free(s_cert2);
     if (s_key2)
         EVP_PKEY_free(s_key2);
+    if (serverinfo_in != NULL)
+        BIO_free(serverinfo_in);
+# ifndef OPENSSL_NO_NEXTPROTONEG
+    if (next_proto.data)
+        OPENSSL_free(next_proto.data);
+# endif
+    if (alpn_ctx.data)
+        OPENSSL_free(alpn_ctx.data);
+#endif
+    ssl_excert_free(exc);
+    if (ssl_args)
+        sk_OPENSSL_STRING_free(ssl_args);
+    if (cctx)
+        SSL_CONF_CTX_free(cctx);
+#ifndef OPENSSL_NO_JPAKE
+    if (jpake_secret && psk_key)
+        OPENSSL_free(psk_key);
 #endif
     if (bio_s_out != NULL) {
         BIO_free(bio_s_out);
         bio_s_out = NULL;
     }
+    if (bio_s_msg != NULL) {
+        BIO_free(bio_s_msg);
+        bio_s_msg = NULL;
+    }
     apps_shutdown();
     OPENSSL_EXIT(ret);
 }
@@ -1952,7 +2155,7 @@ static void print_stats(BIO *bio, SSL_CTX *ssl_ctx)
                SSL_CTX_sess_get_cache_size(ssl_ctx));
 }
 
-static int sv_body(char *hostname, int s, unsigned char *context)
+static int sv_body(char *hostname, int s, int stype, unsigned char *context)
 {
     char *buf = NULL;
     fd_set readfds;
@@ -2016,7 +2219,7 @@ static int sv_body(char *hostname, int s, unsigned char *context)
 # endif
 #endif
 
-    if (SSL_version(con) == DTLS1_VERSION) {
+    if (stype == SOCK_DGRAM) {
 
         sbio = BIO_new_dgram(s, BIO_NOCLOSE);
 
@@ -2075,8 +2278,13 @@ static int sv_body(char *hostname, int s, unsigned char *context)
         BIO_set_callback_arg(SSL_get_rbio(con), (char *)bio_s_out);
     }
     if (s_msg) {
-        SSL_set_msg_callback(con, msg_cb);
-        SSL_set_msg_callback_arg(con, bio_s_out);
+#ifndef OPENSSL_NO_SSL_TRACE
+        if (s_msg == 2)
+            SSL_set_msg_callback(con, SSL_trace);
+        else
+#endif
+            SSL_set_msg_callback(con, msg_cb);
+        SSL_set_msg_callback_arg(con, bio_s_msg ? bio_s_msg : bio_s_out);
     }
 #ifndef OPENSSL_NO_TLSEXT
     if (s_tlsextdebug) {
@@ -2174,7 +2382,7 @@ static int sv_body(char *hostname, int s, unsigned char *context)
                 assert(lf_num == 0);
             } else
                 i = raw_read_stdin(buf, bufsize);
-            if (!s_quiet) {
+            if (!s_quiet && !s_brief) {
                 if ((i <= 0) || (buf[0] == 'Q')) {
                     BIO_printf(bio_s_out, "DONE\n");
                     SHUTDOWN(s);
@@ -2391,6 +2599,16 @@ static int init_ssl_connection(SSL *con)
     unsigned char *exportedkeymat;
 
     i = SSL_accept(con);
+#ifdef CERT_CB_TEST_RETRY
+    {
+        while (i <= 0 && SSL_get_error(con, i) == SSL_ERROR_WANT_X509_LOOKUP
+               && SSL_state(con) == SSL3_ST_SR_CLNT_HELLO_C) {
+            fprintf(stderr,
+                    "LOOKUP from certificate callback during accept\n");
+            i = SSL_accept(con);
+        }
+    }
+#endif
 #ifndef OPENSSL_NO_SRP
     while (i <= 0 && SSL_get_error(con, i) == SSL_ERROR_WANT_X509_LOOKUP) {
         BIO_printf(bio_s_out, "LOOKUP during accept %s\n",
@@ -2407,6 +2625,7 @@ static int init_ssl_connection(SSL *con)
         i = SSL_accept(con);
     }
 #endif
+
     if (i <= 0) {
         if (BIO_sock_should_retry(i)) {
             BIO_printf(bio_s_out, "DELAY\n");
@@ -2418,11 +2637,15 @@ static int init_ssl_connection(SSL *con)
         if (verify_error != X509_V_OK) {
             BIO_printf(bio_err, "verify error:%s\n",
                        X509_verify_cert_error_string(verify_error));
-        } else
-            ERR_print_errors(bio_err);
+        }
+        /* Always print any error messages */
+        ERR_print_errors(bio_err);
         return (0);
     }
 
+    if (s_brief)
+        print_ssl_summary(bio_err, con);
+
     PEM_write_bio_SSL_SESSION(bio_s_out, SSL_get_session(con));
 
     peer = SSL_get_peer_certificate(con);
@@ -2439,6 +2662,11 @@ static int init_ssl_connection(SSL *con)
     if (SSL_get_shared_ciphers(con, buf, sizeof buf) != NULL)
         BIO_printf(bio_s_out, "Shared ciphers:%s\n", buf);
     str = SSL_CIPHER_get_name(SSL_get_current_cipher(con));
+    ssl_print_sigalgs(bio_s_out, con);
+#ifndef OPENSSL_NO_EC
+    ssl_print_point_formats(bio_s_out, con);
+    ssl_print_curves(bio_s_out, con, 0);
+#endif
     BIO_printf(bio_s_out, "CIPHER is %s\n", (str != NULL) ? str : "(NONE)");
 
 #if !defined(OPENSSL_NO_TLSEXT) && !defined(OPENSSL_NO_NEXTPROTONEG)
@@ -2538,7 +2766,7 @@ static int load_CA(SSL_CTX *ctx, char *file)
 }
 #endif
 
-static int www_body(char *hostname, int s, unsigned char *context)
+static int www_body(char *hostname, int s, int stype, unsigned char *context)
 {
     char *buf = NULL;
     int ret = 1;
@@ -2613,8 +2841,13 @@ static int www_body(char *hostname, int s, unsigned char *context)
         BIO_set_callback_arg(SSL_get_rbio(con), (char *)bio_s_out);
     }
     if (s_msg) {
-        SSL_set_msg_callback(con, msg_cb);
-        SSL_set_msg_callback_arg(con, bio_s_out);
+#ifndef OPENSSL_NO_SSL_TRACE
+        if (s_msg == 2)
+            SSL_set_msg_callback(con, SSL_trace);
+        else
+#endif
+            SSL_set_msg_callback(con, msg_cb);
+        SSL_set_msg_callback_arg(con, bio_s_msg ? bio_s_msg : bio_s_out);
     }
 
     for (;;) {
@@ -2750,6 +2983,10 @@ static int www_body(char *hostname, int s, unsigned char *context)
                 }
                 BIO_puts(io, "\n");
             }
+            ssl_print_sigalgs(io, con);
+#ifndef OPENSSL_NO_EC
+            ssl_print_curves(io, con, 0);
+#endif
             BIO_printf(io, (SSL_cache_hit(con)
                             ? "---\nReused, " : "---\nNew, "));
             c = SSL_get_current_cipher(con);
@@ -2932,6 +3169,172 @@ static int www_body(char *hostname, int s, unsigned char *context)
     return (ret);
 }
 
+static int rev_body(char *hostname, int s, int stype, unsigned char *context)
+{
+    char *buf = NULL;
+    int i;
+    int ret = 1;
+    SSL *con;
+    BIO *io, *ssl_bio, *sbio;
+#ifndef OPENSSL_NO_KRB5
+    KSSL_CTX *kctx;
+#endif
+
+    buf = OPENSSL_malloc(bufsize);
+    if (buf == NULL)
+        return (0);
+    io = BIO_new(BIO_f_buffer());
+    ssl_bio = BIO_new(BIO_f_ssl());
+    if ((io == NULL) || (ssl_bio == NULL))
+        goto err;
+
+    /* lets make the output buffer a reasonable size */
+    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 ((kctx = kssl_ctx_new()) != NULL) {
+        kssl_ctx_setstring(kctx, KSSL_SERVICE, KRB5SVC);
+        kssl_ctx_setstring(kctx, KSSL_KEYTAB, KRB5KEYTAB);
+    }
+#endif                          /* OPENSSL_NO_KRB5 */
+    if (context)
+        SSL_set_session_id_context(con, context, strlen((char *)context));
+
+    sbio = BIO_new_socket(s, BIO_NOCLOSE);
+    SSL_set_bio(con, sbio, sbio);
+    SSL_set_accept_state(con);
+
+    BIO_set_ssl(ssl_bio, con, BIO_CLOSE);
+    BIO_push(io, ssl_bio);
+#ifdef CHARSET_EBCDIC
+    io = BIO_push(BIO_new(BIO_f_ebcdic_filter()), io);
+#endif
+
+    if (s_debug) {
+        SSL_set_debug(con, 1);
+        BIO_set_callback(SSL_get_rbio(con), bio_dump_callback);
+        BIO_set_callback_arg(SSL_get_rbio(con), (char *)bio_s_out);
+    }
+    if (s_msg) {
+#ifndef OPENSSL_NO_SSL_TRACE
+        if (s_msg == 2)
+            SSL_set_msg_callback(con, SSL_trace);
+        else
+#endif
+            SSL_set_msg_callback(con, msg_cb);
+        SSL_set_msg_callback_arg(con, bio_s_msg ? bio_s_msg : bio_s_out);
+    }
+
+    for (;;) {
+        i = BIO_do_handshake(io);
+        if (i > 0)
+            break;
+        if (!BIO_should_retry(io)) {
+            BIO_puts(bio_err, "CONNECTION FAILURE\n");
+            ERR_print_errors(bio_err);
+            goto end;
+        }
+#ifndef OPENSSL_NO_SRP
+        if (BIO_should_io_special(io)
+            && BIO_get_retry_reason(io) == BIO_RR_SSL_X509_LOOKUP) {
+            BIO_printf(bio_s_out, "LOOKUP renego during accept\n");
+            SRP_user_pwd_free(srp_callback_parm.user);
+            srp_callback_parm.user =
+                SRP_VBASE_get1_by_user(srp_callback_parm.vb,
+                                       srp_callback_parm.login);
+            if (srp_callback_parm.user)
+                BIO_printf(bio_s_out, "LOOKUP done %s\n",
+                           srp_callback_parm.user->info);
+            else
+                BIO_printf(bio_s_out, "LOOKUP not successful\n");
+            continue;
+        }
+#endif
+    }
+    BIO_printf(bio_err, "CONNECTION ESTABLISHED\n");
+    print_ssl_summary(bio_err, con);
+
+    for (;;) {
+        i = BIO_gets(io, buf, bufsize - 1);
+        if (i < 0) {            /* error */
+            if (!BIO_should_retry(io)) {
+                if (!s_quiet)
+                    ERR_print_errors(bio_err);
+                goto err;
+            } else {
+                BIO_printf(bio_s_out, "read R BLOCK\n");
+#ifndef OPENSSL_NO_SRP
+                if (BIO_should_io_special(io)
+                    && BIO_get_retry_reason(io) == BIO_RR_SSL_X509_LOOKUP) {
+                    BIO_printf(bio_s_out, "LOOKUP renego during read\n");
+                    SRP_user_pwd_free(srp_callback_parm.user);
+                    srp_callback_parm.user =
+                        SRP_VBASE_get1_by_user(srp_callback_parm.vb,
+                                               srp_callback_parm.login);
+                    if (srp_callback_parm.user)
+                        BIO_printf(bio_s_out, "LOOKUP done %s\n",
+                                   srp_callback_parm.user->info);
+                    else
+                        BIO_printf(bio_s_out, "LOOKUP not successful\n");
+                    continue;
+                }
+#endif
+#if defined(OPENSSL_SYS_NETWARE)
+                delay(1000);
+#elif !defined(OPENSSL_SYS_MSDOS) && !defined(__DJGPP__)
+                sleep(1);
+#endif
+                continue;
+            }
+        } else if (i == 0) {    /* end of input */
+            ret = 1;
+            BIO_printf(bio_err, "CONNECTION CLOSED\n");
+            goto end;
+        } else {
+            char *p = buf + i - 1;
+            while (i && (*p == '\n' || *p == '\r')) {
+                p--;
+                i--;
+            }
+            if (!s_ign_eof && i == 5 && !strncmp(buf, "CLOSE", 5)) {
+                ret = 1;
+                BIO_printf(bio_err, "CONNECTION CLOSED\n");
+                goto end;
+            }
+            BUF_reverse((unsigned char *)buf, NULL, i);
+            buf[i] = '\n';
+            BIO_write(io, buf, i + 1);
+            for (;;) {
+                i = BIO_flush(io);
+                if (i > 0)
+                    break;
+                if (!BIO_should_retry(io))
+                    goto end;
+            }
+        }
+    }
+ end:
+    /* make sure we re-use sessions */
+    SSL_set_shutdown(con, SSL_SENT_SHUTDOWN | SSL_RECEIVED_SHUTDOWN);
+
+ err:
+
+    if (buf != NULL)
+        OPENSSL_free(buf);
+    if (io != NULL)
+        BIO_free_all(io);
+    return (ret);
+}
+
 #ifndef OPENSSL_NO_RSA
 static RSA MS_CALLBACK *tmp_rsa_cb(SSL *s, int is_export, int keylength)
 {
@@ -2987,3 +3390,116 @@ static int generate_session_id(const SSL *ssl, unsigned char *id,
         return 0;
     return 1;
 }
+
+/*
+ * By default s_server uses an in-memory cache which caches SSL_SESSION
+ * structures without any serialisation. This hides some bugs which only
+ * become apparent in deployed servers. By implementing a basic external
+ * session cache some issues can be debugged using s_server.
+ */
+
+typedef struct simple_ssl_session_st {
+    unsigned char *id;
+    unsigned int idlen;
+    unsigned char *der;
+    int derlen;
+    struct simple_ssl_session_st *next;
+} simple_ssl_session;
+
+static simple_ssl_session *first = NULL;
+
+static int add_session(SSL *ssl, SSL_SESSION *session)
+{
+    simple_ssl_session *sess;
+    unsigned char *p;
+
+    sess = OPENSSL_malloc(sizeof(simple_ssl_session));
+    if (!sess) {
+        BIO_printf(bio_err, "Out of memory adding session to external cache\n");
+        return 0;
+    }
+
+    SSL_SESSION_get_id(session, &sess->idlen);
+    sess->derlen = i2d_SSL_SESSION(session, NULL);
+
+    sess->id = BUF_memdup(SSL_SESSION_get_id(session, NULL), sess->idlen);
+
+    sess->der = OPENSSL_malloc(sess->derlen);
+    if (!sess->id || !sess->der) {
+        BIO_printf(bio_err, "Out of memory adding session to external cache\n");
+
+        if (sess->id)
+            OPENSSL_free(sess->id);
+        if (sess->der)
+            OPENSSL_free(sess->der);
+        OPENSSL_free(sess);
+        return 0;
+    }
+    p = sess->der;
+    i2d_SSL_SESSION(session, &p);
+
+    sess->next = first;
+    first = sess;
+    BIO_printf(bio_err, "New session added to external cache\n");
+    return 0;
+}
+
+static SSL_SESSION *get_session(SSL *ssl, unsigned char *id, int idlen,
+                                int *do_copy)
+{
+    simple_ssl_session *sess;
+    *do_copy = 0;
+    for (sess = first; sess; sess = sess->next) {
+        if (idlen == (int)sess->idlen && !memcmp(sess->id, id, idlen)) {
+            const unsigned char *p = sess->der;
+            BIO_printf(bio_err, "Lookup session: cache hit\n");
+            return d2i_SSL_SESSION(NULL, &p, sess->derlen);
+        }
+    }
+    BIO_printf(bio_err, "Lookup session: cache miss\n");
+    return NULL;
+}
+
+static void del_session(SSL_CTX *sctx, SSL_SESSION *session)
+{
+    simple_ssl_session *sess, *prev = NULL;
+    const unsigned char *id;
+    unsigned int idlen;
+    id = SSL_SESSION_get_id(session, &idlen);
+    for (sess = first; sess; sess = sess->next) {
+        if (idlen == sess->idlen && !memcmp(sess->id, id, idlen)) {
+            if (prev)
+                prev->next = sess->next;
+            else
+                first = sess->next;
+            OPENSSL_free(sess->id);
+            OPENSSL_free(sess->der);
+            OPENSSL_free(sess);
+            return;
+        }
+        prev = sess;
+    }
+}
+
+static void init_session_cache_ctx(SSL_CTX *sctx)
+{
+    SSL_CTX_set_session_cache_mode(sctx,
+                                   SSL_SESS_CACHE_NO_INTERNAL |
+                                   SSL_SESS_CACHE_SERVER);
+    SSL_CTX_sess_set_new_cb(sctx, add_session);
+    SSL_CTX_sess_set_get_cb(sctx, get_session);
+    SSL_CTX_sess_set_remove_cb(sctx, del_session);
+}
+
+static void free_sessions(void)
+{
+    simple_ssl_session *sess, *tsess;
+    for (sess = first; sess;) {
+        OPENSSL_free(sess->id);
+        OPENSSL_free(sess->der);
+        tsess = sess;
+        sess = sess->next;
+        OPENSSL_free(tsess);
+    }
+    first = NULL;
+}
index 9e5565d..77a7688 100644 (file)
@@ -290,8 +290,9 @@ static int init_client_ip(int *sock, unsigned char ip[4], int port, int type)
 }
 
 int do_server(int port, int type, int *ret,
-              int (*cb) (char *hostname, int s, unsigned char *context),
-              unsigned char *context)
+              int (*cb) (char *hostname, int s, int stype,
+                         unsigned char *context), unsigned char *context,
+              int naccept)
 {
     int sock;
     char *name = NULL;
@@ -313,12 +314,14 @@ int do_server(int port, int type, int *ret,
             }
         } else
             sock = accept_socket;
-        i = (*cb) (name, sock, context);
+        i = (*cb) (name, sock, type, context);
         if (name != NULL)
             OPENSSL_free(name);
         if (type == SOCK_STREAM)
             SHUTDOWN2(sock);
-        if (i < 0) {
+        if (naccept != -1)
+            naccept--;
+        if (i < 0 || naccept == 0) {
             SHUTDOWN2(accept_socket);
             return (i);
         }
index 53e43c5..6044ccf 100644 (file)
@@ -634,6 +634,12 @@ int MAIN(int argc, char **argv)
             p7 = PKCS7_sign(NULL, NULL, other, in, flags);
             if (!p7)
                 goto end;
+            if (flags & PKCS7_NOCERTS) {
+                for (i = 0; i < sk_X509_num(other); i++) {
+                    X509 *x = sk_X509_value(other, i);
+                    PKCS7_add_certificate(p7, x);
+                }
+            }
         } else
             flags |= PKCS7_REUSE_DIGEST;
         for (i = 0; i < sk_OPENSSL_STRING_num(sksigners); i++) {
index ef72723..95adcc1 100644 (file)
@@ -366,6 +366,8 @@ static void *KDF1_SHA1(const void *in, size_t inlen, void *out,
 }
 # endif                         /* OPENSSL_NO_ECDH */
 
+static void multiblock_speed(const EVP_CIPHER *evp_cipher);
+
 int MAIN(int, char **);
 
 int MAIN(int argc, char **argv)
@@ -646,6 +648,7 @@ int MAIN(int argc, char **argv)
 # ifndef NO_FORK
     int multi = 0;
 # endif
+    int multiblock = 0;
 
 # ifndef TIMES
     usertime = -1;
@@ -776,6 +779,9 @@ int MAIN(int argc, char **argv)
             mr = 1;
             j--;                /* Otherwise, -mr gets confused with an
                                  * algorithm. */
+        } else if (argc > 0 && !strcmp(*argv, "-mb")) {
+            multiblock = 1;
+            j--;
         } else
 # ifndef OPENSSL_NO_MD2
         if (strcmp(*argv, "md2") == 0)
@@ -1941,6 +1947,20 @@ int MAIN(int argc, char **argv)
 # endif
 
     if (doit[D_EVP]) {
+# ifdef EVP_CIPH_FLAG_TLS1_1_MULTIBLOCK
+        if (multiblock && evp_cipher) {
+            if (!
+                (EVP_CIPHER_flags(evp_cipher) &
+                 EVP_CIPH_FLAG_TLS1_1_MULTIBLOCK)) {
+                fprintf(stderr, "%s is not multi-block capable\n",
+                        OBJ_nid2ln(evp_cipher->nid));
+                goto end;
+            }
+            multiblock_speed(evp_cipher);
+            mret = 0;
+            goto end;
+        }
+# endif
         for (j = 0; j < SIZE_NUM; j++) {
             if (evp_cipher) {
                 EVP_CIPHER_CTX ctx;
@@ -2742,4 +2762,113 @@ static int do_multi(int multi)
     return 1;
 }
 # endif
+
+static void multiblock_speed(const EVP_CIPHER *evp_cipher)
+{
+    static int mblengths[] =
+        { 8 * 1024, 2 * 8 * 1024, 4 * 8 * 1024, 8 * 8 * 1024, 8 * 16 * 1024 };
+    int j, count, num = sizeof(lengths) / sizeof(lengths[0]);
+    const char *alg_name;
+    unsigned char *inp, *out, no_key[32], no_iv[16];
+    EVP_CIPHER_CTX ctx;
+    double d = 0.0;
+
+    inp = OPENSSL_malloc(mblengths[num - 1]);
+    out = OPENSSL_malloc(mblengths[num - 1] + 1024);
+    if (!inp || !out) {
+        BIO_printf(bio_err,"Out of memory\n");
+        goto end;
+    }
+
+
+    EVP_CIPHER_CTX_init(&ctx);
+    EVP_EncryptInit_ex(&ctx, evp_cipher, NULL, no_key, no_iv);
+    EVP_CIPHER_CTX_ctrl(&ctx, EVP_CTRL_AEAD_SET_MAC_KEY, sizeof(no_key),
+                        no_key);
+    alg_name = OBJ_nid2ln(evp_cipher->nid);
+
+    for (j = 0; j < num; j++) {
+        print_message(alg_name, 0, mblengths[j]);
+        Time_F(START);
+        for (count = 0, run = 1; run && count < 0x7fffffff; count++) {
+            unsigned char aad[EVP_AEAD_TLS1_AAD_LEN];
+            EVP_CTRL_TLS1_1_MULTIBLOCK_PARAM mb_param;
+            size_t len = mblengths[j];
+            int packlen;
+
+            memset(aad, 0, 8);  /* avoid uninitialized values */
+            aad[8] = 23;        /* SSL3_RT_APPLICATION_DATA */
+            aad[9] = 3;         /* version */
+            aad[10] = 2;
+            aad[11] = 0;        /* length */
+            aad[12] = 0;
+            mb_param.out = NULL;
+            mb_param.inp = aad;
+            mb_param.len = len;
+            mb_param.interleave = 8;
+
+            packlen = EVP_CIPHER_CTX_ctrl(&ctx,
+                                          EVP_CTRL_TLS1_1_MULTIBLOCK_AAD,
+                                          sizeof(mb_param), &mb_param);
+
+            if (packlen > 0) {
+                mb_param.out = out;
+                mb_param.inp = inp;
+                mb_param.len = len;
+                EVP_CIPHER_CTX_ctrl(&ctx,
+                                    EVP_CTRL_TLS1_1_MULTIBLOCK_ENCRYPT,
+                                    sizeof(mb_param), &mb_param);
+            } else {
+                int pad;
+
+                RAND_bytes(out, 16);
+                len += 16;
+                aad[11] = len >> 8;
+                aad[12] = len;
+                pad = EVP_CIPHER_CTX_ctrl(&ctx,
+                                          EVP_CTRL_AEAD_TLS1_AAD,
+                                          EVP_AEAD_TLS1_AAD_LEN, aad);
+                EVP_Cipher(&ctx, out, inp, len + pad);
+            }
+        }
+        d = Time_F(STOP);
+        BIO_printf(bio_err,
+                   mr ? "+R:%d:%s:%f\n"
+                   : "%d %s's in %.2fs\n", count, "evp", d);
+        results[D_EVP][j] = ((double)count) / d * mblengths[j];
+    }
+
+    if (mr) {
+        fprintf(stdout, "+H");
+        for (j = 0; j < num; j++)
+            fprintf(stdout, ":%d", mblengths[j]);
+        fprintf(stdout, "\n");
+        fprintf(stdout, "+F:%d:%s", D_EVP, alg_name);
+        for (j = 0; j < num; j++)
+            fprintf(stdout, ":%.2f", results[D_EVP][j]);
+        fprintf(stdout, "\n");
+    } else {
+        fprintf(stdout,
+                "The 'numbers' are in 1000s of bytes per second processed.\n");
+        fprintf(stdout, "type                    ");
+        for (j = 0; j < num; j++)
+            fprintf(stdout, "%7d bytes", mblengths[j]);
+        fprintf(stdout, "\n");
+        fprintf(stdout, "%-24s", alg_name);
+
+        for (j = 0; j < num; j++) {
+            if (results[D_EVP][j] > 10000)
+                fprintf(stdout, " %11.2fk", results[D_EVP][j] / 1e3);
+            else
+                fprintf(stdout, " %11.2f ", results[D_EVP][j]);
+        }
+        fprintf(stdout, "\n");
+    }
+
+end:
+    if (inp)
+        OPENSSL_free(inp);
+    if (out)
+        OPENSSL_free(out);
+}
 #endif
index e29f9bb..78e729f 100644 (file)
@@ -88,6 +88,7 @@ int MAIN(int argc, char **argv)
     X509_STORE *cert_ctx = NULL;
     X509_LOOKUP *lookup = NULL;
     X509_VERIFY_PARAM *vpm = NULL;
+    int crl_download = 0;
 #ifndef OPENSSL_NO_ENGINE
     char *engine = NULL;
 #endif
@@ -136,7 +137,8 @@ int MAIN(int argc, char **argv)
                 if (argc-- < 1)
                     goto end;
                 crlfile = *(++argv);
-            }
+            } else if (strcmp(*argv, "-crl_download") == 0)
+                crl_download = 1;
 #ifndef OPENSSL_NO_ENGINE
             else if (strcmp(*argv, "-engine") == 0) {
                 if (--argc < 1)
@@ -214,6 +216,9 @@ int MAIN(int argc, char **argv)
     }
 
     ret = 0;
+
+    if (crl_download)
+        store_setup_crl_download(cert_ctx);
     if (argc < 1) {
         if (1 != check(cert_ctx, NULL, untrusted, trusted, crls, e))
             ret = -1;
index e5fe610..7c215bc 100644 (file)
@@ -150,6 +150,9 @@ static const char *x509_usage[] = {
     " -engine e       - use engine e, possibly a hardware device.\n",
 #endif
     " -certopt arg    - various certificate text options\n",
+    " -checkhost host - check certificate matches \"host\"\n",
+    " -checkemail email - check certificate matches \"email\"\n",
+    " -checkip ipaddr - check certificate matches \"ipaddr\"\n",
     NULL
 };
 
@@ -163,6 +166,9 @@ static int x509_certify(X509_STORE *ctx, char *CAfile, const EVP_MD *digest,
                         char *section, ASN1_INTEGER *sno);
 static int purpose_print(BIO *bio, X509 *cert, X509_PURPOSE *pt);
 static int reqfile = 0;
+#ifdef OPENSSL_SSL_DEBUG_BROKEN_PROTOCOL
+static int force_version = 2;
+#endif
 
 int MAIN(int, char **);
 
@@ -174,15 +180,16 @@ int MAIN(int argc, char **argv)
     X509 *x = NULL, *xca = NULL;
     ASN1_OBJECT *objtmp;
     STACK_OF(OPENSSL_STRING) *sigopts = NULL;
-    EVP_PKEY *Upkey = NULL, *CApkey = NULL;
+    EVP_PKEY *Upkey = NULL, *CApkey = NULL, *fkey = NULL;
     ASN1_INTEGER *sno = NULL;
-    int i, num, badops = 0;
+    int i, num, badops = 0, badsig = 0;
     BIO *out = NULL;
     BIO *STDout = NULL;
     STACK_OF(ASN1_OBJECT) *trust = NULL, *reject = NULL;
     int informat, outformat, keyformat, CAformat, CAkeyformat;
     char *infile = NULL, *outfile = NULL, *keyfile = NULL, *CAfile = NULL;
     char *CAkeyfile = NULL, *CAserial = NULL;
+    char *fkeyfile = NULL;
     char *alias = NULL;
     int text = 0, serial = 0, subject = 0, issuer = 0, startdate =
         0, enddate = 0;
@@ -208,6 +215,9 @@ int MAIN(int argc, char **argv)
     int need_rand = 0;
     int checkend = 0, checkoffset = 0;
     unsigned long nmflag = 0, certflag = 0;
+    char *checkhost = NULL;
+    char *checkemail = NULL;
+    char *checkip = NULL;
 #ifndef OPENSSL_NO_ENGINE
     char *engine = NULL;
 #endif
@@ -274,7 +284,15 @@ int MAIN(int argc, char **argv)
                 sigopts = sk_OPENSSL_STRING_new_null();
             if (!sigopts || !sk_OPENSSL_STRING_push(sigopts, *(++argv)))
                 goto bad;
-        } else if (strcmp(*argv, "-days") == 0) {
+        }
+#ifdef OPENSSL_SSL_DEBUG_BROKEN_PROTOCOL
+        else if (strcmp(*argv, "-force_version") == 0) {
+            if (--argc < 1)
+                goto bad;
+            force_version = atoi(*(++argv)) - 1;
+        }
+#endif
+        else if (strcmp(*argv, "-days") == 0) {
             if (--argc < 1)
                 goto bad;
             days = atoi(*(++argv));
@@ -327,6 +345,10 @@ int MAIN(int argc, char **argv)
                 goto bad;
             if (!(sno = s2i_ASN1_INTEGER(NULL, *(++argv))))
                 goto bad;
+        } else if (strcmp(*argv, "-force_pubkey") == 0) {
+            if (--argc < 1)
+                goto bad;
+            fkeyfile = *(++argv);
         } else if (strcmp(*argv, "-addtrust") == 0) {
             if (--argc < 1)
                 goto bad;
@@ -424,6 +446,18 @@ int MAIN(int argc, char **argv)
                 goto bad;
             checkoffset = atoi(*(++argv));
             checkend = 1;
+        } else if (strcmp(*argv, "-checkhost") == 0) {
+            if (--argc < 1)
+                goto bad;
+            checkhost = *(++argv);
+        } else if (strcmp(*argv, "-checkemail") == 0) {
+            if (--argc < 1)
+                goto bad;
+            checkemail = *(++argv);
+        } else if (strcmp(*argv, "-checkip") == 0) {
+            if (--argc < 1)
+                goto bad;
+            checkip = *(++argv);
         } else if (strcmp(*argv, "-noout") == 0)
             noout = ++num;
         else if (strcmp(*argv, "-trustout") == 0)
@@ -447,6 +481,8 @@ int MAIN(int argc, char **argv)
 #endif
         else if (strcmp(*argv, "-ocspid") == 0)
             ocspid = ++num;
+        else if (strcmp(*argv, "-badsig") == 0)
+            badsig = 1;
         else if ((md_alg = EVP_get_digestbyname(*argv + 1))) {
             /* ok */
             digest = md_alg;
@@ -484,6 +520,13 @@ int MAIN(int argc, char **argv)
         goto end;
     }
 
+    if (fkeyfile) {
+        fkey = load_pubkey(bio_err, fkeyfile, keyformat, 0,
+                           NULL, e, "Forced key");
+        if (fkey == NULL)
+            goto end;
+    }
+
     if ((CAkeyfile == NULL) && (CA_flag) && (CAformat == FORMAT_PEM)) {
         CAkeyfile = CAfile;
     } else if ((CA_flag) && (CAkeyfile == NULL)) {
@@ -605,10 +648,13 @@ int MAIN(int argc, char **argv)
 
         X509_gmtime_adj(X509_get_notBefore(x), 0);
         X509_time_adj_ex(X509_get_notAfter(x), days, 0, NULL);
-
-        pkey = X509_REQ_get_pubkey(req);
-        X509_set_pubkey(x, pkey);
-        EVP_PKEY_free(pkey);
+        if (fkey)
+            X509_set_pubkey(x, fkey);
+        else {
+            pkey = X509_REQ_get_pubkey(req);
+            X509_set_pubkey(x, pkey);
+            EVP_PKEY_free(pkey);
+        }
     } else
         x = load_cert(bio_err, infile, informat, NULL, e, "Certificate");
 
@@ -937,11 +983,16 @@ int MAIN(int argc, char **argv)
         goto end;
     }
 
+    print_cert_checks(STDout, x, checkhost, checkemail, checkip);
+
     if (noout) {
         ret = 0;
         goto end;
     }
 
+    if (badsig)
+        x->signature->data[x->signature->length - 1] ^= 0x1;
+
     if (outformat == FORMAT_ASN1)
         i = i2d_X509_bio(out, x);
     else if (outformat == FORMAT_PEM) {
@@ -982,6 +1033,7 @@ int MAIN(int argc, char **argv)
     X509_free(xca);
     EVP_PKEY_free(Upkey);
     EVP_PKEY_free(CApkey);
+    EVP_PKEY_free(fkey);
     if (sigopts)
         sk_OPENSSL_STRING_free(sigopts);
     X509_REQ_free(rq);
@@ -1101,7 +1153,11 @@ static int x509_certify(X509_STORE *ctx, char *CAfile, const EVP_MD *digest,
 
     if (conf) {
         X509V3_CTX ctx2;
+#ifdef OPENSSL_SSL_DEBUG_BROKEN_PROTOCOL
+        X509_set_version(x, force_version);
+#else
         X509_set_version(x, 2); /* version 3 certificate */
+#endif
         X509V3_set_ctx(&ctx2, xca, x, NULL, NULL, 0);
         X509V3_set_nconf(&ctx2, conf);
         if (!X509V3_EXT_add_nconf(conf, &ctx2, section, x))
@@ -1181,7 +1237,11 @@ static int sign(X509 *x, EVP_PKEY *pkey, int days, int clrext,
     }
     if (conf) {
         X509V3_CTX ctx;
+#ifdef OPENSSL_SSL_DEBUG_BROKEN_PROTOCOL
+        X509_set_version(x, force_version);
+#else
         X509_set_version(x, 2); /* version 3 certificate */
+#endif
         X509V3_set_ctx(&ctx, x, x, NULL, NULL, 0);
         X509V3_set_nconf(&ctx, conf);
         if (!X509V3_EXT_add_nconf(conf, &ctx, section, x))
index b1ab8e2..b7b64d5 100644 (file)
 
 #include "cryptlib.h"
 #include <openssl/aes.h>
-#include <openssl/bio.h>
-
-static const unsigned char default_iv[] = {
-    0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6,
-};
+#include <openssl/modes.h>
 
 int AES_wrap_key(AES_KEY *key, const unsigned char *iv,
                  unsigned char *out,
                  const unsigned char *in, unsigned int inlen)
 {
-    unsigned char *A, B[16], *R;
-    unsigned int i, j, t;
-    if ((inlen & 0x7) || (inlen < 8))
-        return -1;
-    A = B;
-    t = 1;
-    memcpy(out + 8, in, inlen);
-    if (!iv)
-        iv = default_iv;
-
-    memcpy(A, iv, 8);
-
-    for (j = 0; j < 6; j++) {
-        R = out + 8;
-        for (i = 0; i < inlen; i += 8, t++, R += 8) {
-            memcpy(B + 8, R, 8);
-            AES_encrypt(B, B, key);
-            A[7] ^= (unsigned char)(t & 0xff);
-            if (t > 0xff) {
-                A[6] ^= (unsigned char)((t >> 8) & 0xff);
-                A[5] ^= (unsigned char)((t >> 16) & 0xff);
-                A[4] ^= (unsigned char)((t >> 24) & 0xff);
-            }
-            memcpy(R, B + 8, 8);
-        }
-    }
-    memcpy(out, A, 8);
-    return inlen + 8;
+    return CRYPTO_128_wrap(key, iv, out, in, inlen, (block128_f) AES_encrypt);
 }
 
 int AES_unwrap_key(AES_KEY *key, const unsigned char *iv,
                    unsigned char *out,
                    const unsigned char *in, unsigned int inlen)
 {
-    unsigned char *A, B[16], *R;
-    unsigned int i, j, t;
-    inlen -= 8;
-    if (inlen & 0x7)
-        return -1;
-    if (inlen < 8)
-        return -1;
-    A = B;
-    t = 6 * (inlen >> 3);
-    memcpy(A, in, 8);
-    memcpy(out, in + 8, inlen);
-    for (j = 0; j < 6; j++) {
-        R = out + inlen - 8;
-        for (i = 0; i < inlen; i += 8, t--, R -= 8) {
-            A[7] ^= (unsigned char)(t & 0xff);
-            if (t > 0xff) {
-                A[6] ^= (unsigned char)((t >> 8) & 0xff);
-                A[5] ^= (unsigned char)((t >> 16) & 0xff);
-                A[4] ^= (unsigned char)((t >> 24) & 0xff);
-            }
-            memcpy(B + 8, R, 8);
-            AES_decrypt(B, B, key);
-            memcpy(R, B + 8, 8);
-        }
-    }
-    if (!iv)
-        iv = default_iv;
-    if (memcmp(A, iv, 8)) {
-        OPENSSL_cleanse(out, inlen);
-        return 0;
-    }
-    return inlen;
-}
-
-#ifdef AES_WRAP_TEST
-
-int AES_wrap_unwrap_test(const unsigned char *kek, int keybits,
-                         const unsigned char *iv,
-                         const unsigned char *eout,
-                         const unsigned char *key, int keylen)
-{
-    unsigned char *otmp = NULL, *ptmp = NULL;
-    int r, ret = 0;
-    AES_KEY wctx;
-    otmp = OPENSSL_malloc(keylen + 8);
-    ptmp = OPENSSL_malloc(keylen);
-    if (!otmp || !ptmp)
-        return 0;
-    if (AES_set_encrypt_key(kek, keybits, &wctx))
-        goto err;
-    r = AES_wrap_key(&wctx, iv, otmp, key, keylen);
-    if (r <= 0)
-        goto err;
-
-    if (eout && memcmp(eout, otmp, keylen))
-        goto err;
-
-    if (AES_set_decrypt_key(kek, keybits, &wctx))
-        goto err;
-    r = AES_unwrap_key(&wctx, iv, ptmp, otmp, r);
-
-    if (memcmp(key, ptmp, keylen))
-        goto err;
-
-    ret = 1;
-
- err:
-    if (otmp)
-        OPENSSL_free(otmp);
-    if (ptmp)
-        OPENSSL_free(ptmp);
-
-    return ret;
-
+    return CRYPTO_128_unwrap(key, iv, out, in, inlen,
+                             (block128_f) AES_decrypt);
 }
-
-int main(int argc, char **argv)
-{
-
-    static const unsigned char kek[] = {
-        0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
-        0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
-        0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
-        0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f
-    };
-
-    static const unsigned char key[] = {
-        0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
-        0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff,
-        0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
-        0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f
-    };
-
-    static const unsigned char e1[] = {
-        0x1f, 0xa6, 0x8b, 0x0a, 0x81, 0x12, 0xb4, 0x47,
-        0xae, 0xf3, 0x4b, 0xd8, 0xfb, 0x5a, 0x7b, 0x82,
-        0x9d, 0x3e, 0x86, 0x23, 0x71, 0xd2, 0xcf, 0xe5
-    };
-
-    static const unsigned char e2[] = {
-        0x96, 0x77, 0x8b, 0x25, 0xae, 0x6c, 0xa4, 0x35,
-        0xf9, 0x2b, 0x5b, 0x97, 0xc0, 0x50, 0xae, 0xd2,
-        0x46, 0x8a, 0xb8, 0xa1, 0x7a, 0xd8, 0x4e, 0x5d
-    };
-
-    static const unsigned char e3[] = {
-        0x64, 0xe8, 0xc3, 0xf9, 0xce, 0x0f, 0x5b, 0xa2,
-        0x63, 0xe9, 0x77, 0x79, 0x05, 0x81, 0x8a, 0x2a,
-        0x93, 0xc8, 0x19, 0x1e, 0x7d, 0x6e, 0x8a, 0xe7
-    };
-
-    static const unsigned char e4[] = {
-        0x03, 0x1d, 0x33, 0x26, 0x4e, 0x15, 0xd3, 0x32,
-        0x68, 0xf2, 0x4e, 0xc2, 0x60, 0x74, 0x3e, 0xdc,
-        0xe1, 0xc6, 0xc7, 0xdd, 0xee, 0x72, 0x5a, 0x93,
-        0x6b, 0xa8, 0x14, 0x91, 0x5c, 0x67, 0x62, 0xd2
-    };
-
-    static const unsigned char e5[] = {
-        0xa8, 0xf9, 0xbc, 0x16, 0x12, 0xc6, 0x8b, 0x3f,
-        0xf6, 0xe6, 0xf4, 0xfb, 0xe3, 0x0e, 0x71, 0xe4,
-        0x76, 0x9c, 0x8b, 0x80, 0xa3, 0x2c, 0xb8, 0x95,
-        0x8c, 0xd5, 0xd1, 0x7d, 0x6b, 0x25, 0x4d, 0xa1
-    };
-
-    static const unsigned char e6[] = {
-        0x28, 0xc9, 0xf4, 0x04, 0xc4, 0xb8, 0x10, 0xf4,
-        0xcb, 0xcc, 0xb3, 0x5c, 0xfb, 0x87, 0xf8, 0x26,
-        0x3f, 0x57, 0x86, 0xe2, 0xd8, 0x0e, 0xd3, 0x26,
-        0xcb, 0xc7, 0xf0, 0xe7, 0x1a, 0x99, 0xf4, 0x3b,
-        0xfb, 0x98, 0x8b, 0x9b, 0x7a, 0x02, 0xdd, 0x21
-    };
-
-    AES_KEY wctx, xctx;
-    int ret;
-    ret = AES_wrap_unwrap_test(kek, 128, NULL, e1, key, 16);
-    fprintf(stderr, "Key test result %d\n", ret);
-    ret = AES_wrap_unwrap_test(kek, 192, NULL, e2, key, 16);
-    fprintf(stderr, "Key test result %d\n", ret);
-    ret = AES_wrap_unwrap_test(kek, 256, NULL, e3, key, 16);
-    fprintf(stderr, "Key test result %d\n", ret);
-    ret = AES_wrap_unwrap_test(kek, 192, NULL, e4, key, 24);
-    fprintf(stderr, "Key test result %d\n", ret);
-    ret = AES_wrap_unwrap_test(kek, 256, NULL, e5, key, 24);
-    fprintf(stderr, "Key test result %d\n", ret);
-    ret = AES_wrap_unwrap_test(kek, 256, NULL, e6, key, 32);
-    fprintf(stderr, "Key test result %d\n", ret);
-}
-
-#endif
diff --git a/crypto/openssl/crypto/aes/asm/aes-586.pl b/crypto/openssl/crypto/aes/asm/aes-586.pl
deleted file mode 100755 (executable)
index 51b500d..0000000
+++ /dev/null
@@ -1,2980 +0,0 @@
-#!/usr/bin/env perl
-#
-# ====================================================================
-# Written by Andy Polyakov <appro@fy.chalmers.se> for the OpenSSL
-# project. The module is, however, dual licensed under OpenSSL and
-# CRYPTOGAMS licenses depending on where you obtain it. For further
-# details see http://www.openssl.org/~appro/cryptogams/.
-# ====================================================================
-#
-# Version 4.3.
-#
-# You might fail to appreciate this module performance from the first
-# try. If compared to "vanilla" linux-ia32-icc target, i.e. considered
-# to be *the* best Intel C compiler without -KPIC, performance appears
-# to be virtually identical... But try to re-configure with shared
-# library support... Aha! Intel compiler "suddenly" lags behind by 30%
-# [on P4, more on others]:-) And if compared to position-independent
-# code generated by GNU C, this code performs *more* than *twice* as
-# fast! Yes, all this buzz about PIC means that unlike other hand-
-# coded implementations, this one was explicitly designed to be safe
-# to use even in shared library context... This also means that this
-# code isn't necessarily absolutely fastest "ever," because in order
-# to achieve position independence an extra register has to be
-# off-loaded to stack, which affects the benchmark result.
-#
-# Special note about instruction choice. Do you recall RC4_INT code
-# performing poorly on P4? It might be the time to figure out why.
-# RC4_INT code implies effective address calculations in base+offset*4
-# form. Trouble is that it seems that offset scaling turned to be
-# critical path... At least eliminating scaling resulted in 2.8x RC4
-# performance improvement [as you might recall]. As AES code is hungry
-# for scaling too, I [try to] avoid the latter by favoring off-by-2
-# shifts and masking the result with 0xFF<<2 instead of "boring" 0xFF.
-#
-# As was shown by Dean Gaudet <dean@arctic.org>, the above note turned
-# void. Performance improvement with off-by-2 shifts was observed on
-# intermediate implementation, which was spilling yet another register
-# to stack... Final offset*4 code below runs just a tad faster on P4,
-# but exhibits up to 10% improvement on other cores.
-#
-# Second version is "monolithic" replacement for aes_core.c, which in
-# addition to AES_[de|en]crypt implements private_AES_set_[de|en]cryption_key.
-# This made it possible to implement little-endian variant of the
-# algorithm without modifying the base C code. Motivating factor for
-# the undertaken effort was that it appeared that in tight IA-32
-# register window little-endian flavor could achieve slightly higher
-# Instruction Level Parallelism, and it indeed resulted in up to 15%
-# better performance on most recent µ-archs...
-#
-# Third version adds AES_cbc_encrypt implementation, which resulted in
-# up to 40% performance imrovement of CBC benchmark results. 40% was
-# observed on P4 core, where "overall" imrovement coefficient, i.e. if
-# compared to PIC generated by GCC and in CBC mode, was observed to be
-# as large as 4x:-) CBC performance is virtually identical to ECB now
-# and on some platforms even better, e.g. 17.6 "small" cycles/byte on
-# Opteron, because certain function prologues and epilogues are
-# effectively taken out of the loop...
-#
-# Version 3.2 implements compressed tables and prefetch of these tables
-# in CBC[!] mode. Former means that 3/4 of table references are now
-# misaligned, which unfortunately has negative impact on elder IA-32
-# implementations, Pentium suffered 30% penalty, PIII - 10%.
-#
-# Version 3.3 avoids L1 cache aliasing between stack frame and
-# S-boxes, and 3.4 - L1 cache aliasing even between key schedule. The
-# latter is achieved by copying the key schedule to controlled place in
-# stack. This unfortunately has rather strong impact on small block CBC
-# performance, ~2x deterioration on 16-byte block if compared to 3.3.
-#
-# Version 3.5 checks if there is L1 cache aliasing between user-supplied
-# key schedule and S-boxes and abstains from copying the former if
-# there is no. This allows end-user to consciously retain small block
-# performance by aligning key schedule in specific manner.
-#
-# Version 3.6 compresses Td4 to 256 bytes and prefetches it in ECB.
-#
-# Current ECB performance numbers for 128-bit key in CPU cycles per
-# processed byte [measure commonly used by AES benchmarkers] are:
-#
-#              small footprint         fully unrolled
-# P4           24                      22
-# AMD K8       20                      19
-# PIII         25                      23
-# Pentium      81                      78
-#
-# Version 3.7 reimplements outer rounds as "compact." Meaning that
-# first and last rounds reference compact 256 bytes S-box. This means
-# that first round consumes a lot more CPU cycles and that encrypt
-# and decrypt performance becomes asymmetric. Encrypt performance
-# drops by 10-12%, while decrypt - by 20-25%:-( 256 bytes S-box is
-# aggressively pre-fetched.
-#
-# Version 4.0 effectively rolls back to 3.6 and instead implements
-# additional set of functions, _[x86|sse]_AES_[en|de]crypt_compact,
-# which use exclusively 256 byte S-box. These functions are to be
-# called in modes not concealing plain text, such as ECB, or when
-# we're asked to process smaller amount of data [or unconditionally
-# on hyper-threading CPU]. Currently it's called unconditionally from
-# AES_[en|de]crypt, which affects all modes, but CBC. CBC routine
-# still needs to be modified to switch between slower and faster
-# mode when appropriate... But in either case benchmark landscape
-# changes dramatically and below numbers are CPU cycles per processed
-# byte for 128-bit key.
-#
-#              ECB encrypt     ECB decrypt     CBC large chunk
-# P4           56[60]          84[100]         23
-# AMD K8       48[44]          70[79]          18
-# PIII         41[50]          61[91]          24
-# Core 2       32[38]          45[70]          18.5
-# Pentium      120             160             77
-#
-# Version 4.1 switches to compact S-box even in key schedule setup.
-#
-# Version 4.2 prefetches compact S-box in every SSE round or in other
-# words every cache-line is *guaranteed* to be accessed within ~50
-# cycles window. Why just SSE? Because it's needed on hyper-threading
-# CPU! Which is also why it's prefetched with 64 byte stride. Best
-# part is that it has no negative effect on performance:-)  
-#
-# Version 4.3 implements switch between compact and non-compact block
-# functions in AES_cbc_encrypt depending on how much data was asked
-# to be processed in one stroke.
-#
-######################################################################
-# Timing attacks are classified in two classes: synchronous when
-# attacker consciously initiates cryptographic operation and collects
-# timing data of various character afterwards, and asynchronous when
-# malicious code is executed on same CPU simultaneously with AES,
-# instruments itself and performs statistical analysis of this data.
-#
-# As far as synchronous attacks go the root to the AES timing
-# vulnerability is twofold. Firstly, of 256 S-box elements at most 160
-# are referred to in single 128-bit block operation. Well, in C
-# implementation with 4 distinct tables it's actually as little as 40
-# references per 256 elements table, but anyway... Secondly, even
-# though S-box elements are clustered into smaller amount of cache-
-# lines, smaller than 160 and even 40, it turned out that for certain
-# plain-text pattern[s] or simply put chosen plain-text and given key
-# few cache-lines remain unaccessed during block operation. Now, if
-# attacker can figure out this access pattern, he can deduct the key
-# [or at least part of it]. The natural way to mitigate this kind of
-# attacks is to minimize the amount of cache-lines in S-box and/or
-# prefetch them to ensure that every one is accessed for more uniform
-# timing. But note that *if* plain-text was concealed in such way that
-# input to block function is distributed *uniformly*, then attack
-# wouldn't apply. Now note that some encryption modes, most notably
-# CBC, do mask the plain-text in this exact way [secure cipher output
-# is distributed uniformly]. Yes, one still might find input that
-# would reveal the information about given key, but if amount of
-# candidate inputs to be tried is larger than amount of possible key
-# combinations then attack becomes infeasible. This is why revised
-# AES_cbc_encrypt "dares" to switch to larger S-box when larger chunk
-# of data is to be processed in one stroke. The current size limit of
-# 512 bytes is chosen to provide same [diminishigly low] probability
-# for cache-line to remain untouched in large chunk operation with
-# large S-box as for single block operation with compact S-box and
-# surely needs more careful consideration...
-#
-# As for asynchronous attacks. There are two flavours: attacker code
-# being interleaved with AES on hyper-threading CPU at *instruction*
-# level, and two processes time sharing single core. As for latter.
-# Two vectors. 1. Given that attacker process has higher priority,
-# yield execution to process performing AES just before timer fires
-# off the scheduler, immediately regain control of CPU and analyze the
-# cache state. For this attack to be efficient attacker would have to
-# effectively slow down the operation by several *orders* of magnitute,
-# by ratio of time slice to duration of handful of AES rounds, which
-# unlikely to remain unnoticed. Not to mention that this also means
-# that he would spend correspondigly more time to collect enough
-# statistical data to mount the attack. It's probably appropriate to
-# say that if adeversary reckons that this attack is beneficial and
-# risks to be noticed, you probably have larger problems having him
-# mere opportunity. In other words suggested code design expects you
-# to preclude/mitigate this attack by overall system security design.
-# 2. Attacker manages to make his code interrupt driven. In order for
-# this kind of attack to be feasible, interrupt rate has to be high
-# enough, again comparable to duration of handful of AES rounds. But
-# is there interrupt source of such rate? Hardly, not even 1Gbps NIC
-# generates interrupts at such raging rate...
-#
-# And now back to the former, hyper-threading CPU or more specifically
-# Intel P4. Recall that asynchronous attack implies that malicious
-# code instruments itself. And naturally instrumentation granularity
-# has be noticeably lower than duration of codepath accessing S-box.
-# Given that all cache-lines are accessed during that time that is.
-# Current implementation accesses *all* cache-lines within ~50 cycles
-# window, which is actually *less* than RDTSC latency on Intel P4!
-
-$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
-push(@INC,"${dir}","${dir}../../perlasm");
-require "x86asm.pl";
-
-&asm_init($ARGV[0],"aes-586.pl",$x86only = $ARGV[$#ARGV] eq "386");
-&static_label("AES_Te");
-&static_label("AES_Td");
-
-$s0="eax";
-$s1="ebx";
-$s2="ecx";
-$s3="edx";
-$key="edi";
-$acc="esi";
-$tbl="ebp";
-
-# stack frame layout in _[x86|sse]_AES_* routines, frame is allocated
-# by caller
-$__ra=&DWP(0,"esp");   # return address
-$__s0=&DWP(4,"esp");   # s0 backing store
-$__s1=&DWP(8,"esp");   # s1 backing store
-$__s2=&DWP(12,"esp");  # s2 backing store
-$__s3=&DWP(16,"esp");  # s3 backing store
-$__key=&DWP(20,"esp"); # pointer to key schedule
-$__end=&DWP(24,"esp"); # pointer to end of key schedule
-$__tbl=&DWP(28,"esp"); # %ebp backing store
-
-# stack frame layout in AES_[en|crypt] routines, which differs from
-# above by 4 and overlaps by %ebp backing store
-$_tbl=&DWP(24,"esp");
-$_esp=&DWP(28,"esp");
-
-sub _data_word() { my $i; while(defined($i=shift)) { &data_word($i,$i); } }
-
-$speed_limit=512;      # chunks smaller than $speed_limit are
-                       # processed with compact routine in CBC mode
-$small_footprint=1;    # $small_footprint=1 code is ~5% slower [on
-                       # recent µ-archs], but ~5 times smaller!
-                       # I favor compact code to minimize cache
-                       # contention and in hope to "collect" 5% back
-                       # in real-life applications...
-
-$vertical_spin=0;      # shift "verticaly" defaults to 0, because of
-                       # its proof-of-concept status...
-# Note that there is no decvert(), as well as last encryption round is
-# performed with "horizontal" shifts. This is because this "vertical"
-# implementation [one which groups shifts on a given $s[i] to form a
-# "column," unlike "horizontal" one, which groups shifts on different
-# $s[i] to form a "row"] is work in progress. It was observed to run
-# few percents faster on Intel cores, but not AMD. On AMD K8 core it's
-# whole 12% slower:-( So we face a trade-off... Shall it be resolved
-# some day? Till then the code is considered experimental and by
-# default remains dormant...
-
-sub encvert()
-{ my ($te,@s) = @_;
-  my $v0 = $acc, $v1 = $key;
-
-       &mov    ($v0,$s[3]);                            # copy s3
-       &mov    (&DWP(4,"esp"),$s[2]);                  # save s2
-       &mov    ($v1,$s[0]);                            # copy s0
-       &mov    (&DWP(8,"esp"),$s[1]);                  # save s1
-
-       &movz   ($s[2],&HB($s[0]));
-       &and    ($s[0],0xFF);
-       &mov    ($s[0],&DWP(0,$te,$s[0],8));            # s0>>0
-       &shr    ($v1,16);
-       &mov    ($s[3],&DWP(3,$te,$s[2],8));            # s0>>8
-       &movz   ($s[1],&HB($v1));
-       &and    ($v1,0xFF);
-       &mov    ($s[2],&DWP(2,$te,$v1,8));              # s0>>16
-        &mov   ($v1,$v0);
-       &mov    ($s[1],&DWP(1,$te,$s[1],8));            # s0>>24
-
-       &and    ($v0,0xFF);
-       &xor    ($s[3],&DWP(0,$te,$v0,8));              # s3>>0