Merge branch 'vendor/OPENSSL'
authorPeter Avalos <pavalos@dragonflybsd.org>
Tue, 27 Mar 2012 23:47:37 +0000 (16:47 -0700)
committerPeter Avalos <pavalos@dragonflybsd.org>
Tue, 27 Mar 2012 23:47:37 +0000 (16:47 -0700)
354 files changed:
crypto/openssl/CHANGES
crypto/openssl/FAQ
crypto/openssl/NEWS
crypto/openssl/README
crypto/openssl/README.DELETED
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/dgst.c
crypto/openssl/apps/enc.c
crypto/openssl/apps/openssl.c
crypto/openssl/apps/progs.h
crypto/openssl/apps/req.c
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/sess_id.c
crypto/openssl/apps/speed.c
crypto/openssl/apps/srp.c [new file with mode: 0644]
crypto/openssl/apps/verify.c
crypto/openssl/apps/x509.c
crypto/openssl/crypto/aes/aes.h
crypto/openssl/crypto/aes/aes_core.c
crypto/openssl/crypto/aes/aes_misc.c
crypto/openssl/crypto/aes/asm/aes-586.pl
crypto/openssl/crypto/aes/asm/aes-x86_64.pl
crypto/openssl/crypto/aes/asm/aesni-sha1-x86_64.pl [new file with mode: 0644]
crypto/openssl/crypto/aes/asm/aesni-x86.pl [new file with mode: 0644]
crypto/openssl/crypto/aes/asm/aesni-x86_64.pl [new file with mode: 0644]
crypto/openssl/crypto/aes/asm/bsaes-x86_64.pl [new file with mode: 0644]
crypto/openssl/crypto/aes/asm/vpaes-x86.pl [new file with mode: 0644]
crypto/openssl/crypto/aes/asm/vpaes-x86_64.pl [new file with mode: 0644]
crypto/openssl/crypto/asn1/a_digest.c
crypto/openssl/crypto/asn1/a_sign.c
crypto/openssl/crypto/asn1/a_verify.c
crypto/openssl/crypto/asn1/ameth_lib.c
crypto/openssl/crypto/asn1/asn1.h
crypto/openssl/crypto/asn1/asn1_err.c
crypto/openssl/crypto/asn1/asn1_locl.h
crypto/openssl/crypto/asn1/asn_mime.c
crypto/openssl/crypto/asn1/n_pkey.c
crypto/openssl/crypto/asn1/p5_pbev2.c
crypto/openssl/crypto/asn1/t_crl.c
crypto/openssl/crypto/asn1/t_x509.c
crypto/openssl/crypto/asn1/x_algor.c
crypto/openssl/crypto/asn1/x_name.c
crypto/openssl/crypto/asn1/x_pubkey.c
crypto/openssl/crypto/bf/bf_skey.c
crypto/openssl/crypto/bf/blowfish.h
crypto/openssl/crypto/bio/bio.h
crypto/openssl/crypto/bio/bio_err.c
crypto/openssl/crypto/bio/bss_bio.c
crypto/openssl/crypto/bio/bss_dgram.c
crypto/openssl/crypto/bn/asm/modexp512-x86_64.pl [new file with mode: 0644]
crypto/openssl/crypto/bn/asm/x86-gf2m.pl [new file with mode: 0644]
crypto/openssl/crypto/bn/asm/x86_64-gf2m.pl [new file with mode: 0644]
crypto/openssl/crypto/bn/asm/x86_64-mont.pl
crypto/openssl/crypto/bn/asm/x86_64-mont5.pl [new file with mode: 0755]
crypto/openssl/crypto/bn/bn.h
crypto/openssl/crypto/bn/bn_div.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/bn_lib.c
crypto/openssl/crypto/bn/bn_mont.c
crypto/openssl/crypto/bn/bn_nist.c
crypto/openssl/crypto/bn/bn_print.c
crypto/openssl/crypto/bn/bn_shift.c
crypto/openssl/crypto/bn/bn_x931p.c [new file with mode: 0644]
crypto/openssl/crypto/buffer/buf_str.c [copied from crypto/openssl/crypto/asn1/a_digest.c with 76% similarity]
crypto/openssl/crypto/buffer/buffer.c
crypto/openssl/crypto/camellia/asm/cmll-x86.pl
crypto/openssl/crypto/camellia/camellia.h
crypto/openssl/crypto/camellia/cmll_locl.h
crypto/openssl/crypto/camellia/cmll_misc.c
crypto/openssl/crypto/camellia/cmll_utl.c [copied from crypto/openssl/crypto/aes/aes_misc.c with 85% similarity]
crypto/openssl/crypto/cast/c_skey.c
crypto/openssl/crypto/cast/cast.h
crypto/openssl/crypto/cmac/cm_ameth.c [copied from crypto/openssl/crypto/ecdh/ech_locl.h with 70% similarity]
crypto/openssl/crypto/cmac/cm_pmeth.c [copied from crypto/openssl/crypto/hmac/hm_pmeth.c with 54% similarity]
crypto/openssl/crypto/cmac/cmac.c [new file with mode: 0644]
crypto/openssl/crypto/cmac/cmac.h [copied from crypto/openssl/crypto/ecdh/ech_locl.h with 71% similarity]
crypto/openssl/crypto/cms/cms.h
crypto/openssl/crypto/cms/cms_asn1.c
crypto/openssl/crypto/cms/cms_enc.c
crypto/openssl/crypto/cms/cms_env.c
crypto/openssl/crypto/cms/cms_err.c
crypto/openssl/crypto/cms/cms_lcl.h
crypto/openssl/crypto/cms/cms_lib.c
crypto/openssl/crypto/cms/cms_pwri.c [new file with mode: 0644]
crypto/openssl/crypto/cms/cms_sd.c
crypto/openssl/crypto/cms/cms_smime.c
crypto/openssl/crypto/comp/c_rle.c
crypto/openssl/crypto/cpt_err.c
crypto/openssl/crypto/cryptlib.c
crypto/openssl/crypto/cryptlib.h
crypto/openssl/crypto/crypto.h
crypto/openssl/crypto/des/des.h
crypto/openssl/crypto/des/set_key.c
crypto/openssl/crypto/dh/dh.h
crypto/openssl/crypto/dh/dh_ameth.c
crypto/openssl/crypto/dh/dh_err.c
crypto/openssl/crypto/dh/dh_gen.c
crypto/openssl/crypto/dh/dh_key.c
crypto/openssl/crypto/dh/dh_lib.c
crypto/openssl/crypto/dsa/dsa.h
crypto/openssl/crypto/dsa/dsa_ameth.c
crypto/openssl/crypto/dsa/dsa_asn1.c
crypto/openssl/crypto/dsa/dsa_err.c
crypto/openssl/crypto/dsa/dsa_gen.c
crypto/openssl/crypto/dsa/dsa_key.c
crypto/openssl/crypto/dsa/dsa_lib.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/dsa/dsa_sign.c
crypto/openssl/crypto/dsa/dsa_vrf.c
crypto/openssl/crypto/dso/dso_dlfcn.c
crypto/openssl/crypto/ec/ec.h
crypto/openssl/crypto/ec/ec2_mult.c
crypto/openssl/crypto/ec/ec2_oct.c [new file with mode: 0644]
crypto/openssl/crypto/ec/ec2_smpl.c
crypto/openssl/crypto/ec/ec_ameth.c
crypto/openssl/crypto/ec/ec_asn1.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_oct.c [new file with mode: 0644]
crypto/openssl/crypto/ec/ec_pmeth.c
crypto/openssl/crypto/ec/eck_prn.c
crypto/openssl/crypto/ec/ecp_mont.c
crypto/openssl/crypto/ec/ecp_nist.c
crypto/openssl/crypto/ec/ecp_nistp224.c [new file with mode: 0644]
crypto/openssl/crypto/ec/ecp_nistp256.c [new file with mode: 0644]
crypto/openssl/crypto/ec/ecp_nistp521.c [new file with mode: 0644]
crypto/openssl/crypto/ec/ecp_nistputil.c [new file with mode: 0644]
crypto/openssl/crypto/ec/ecp_oct.c [new file with mode: 0644]
crypto/openssl/crypto/ec/ecp_smpl.c
crypto/openssl/crypto/ecdh/ecdh.h
crypto/openssl/crypto/ecdh/ech_err.c
crypto/openssl/crypto/ecdh/ech_lib.c
crypto/openssl/crypto/ecdh/ech_locl.h
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_fat.c
crypto/openssl/crypto/engine/eng_rdrand.c [copied from crypto/openssl/crypto/rand/rand_err.c with 57% similarity]
crypto/openssl/crypto/engine/eng_rsax.c [new file with mode: 0644]
crypto/openssl/crypto/engine/engine.h
crypto/openssl/crypto/err/err.c
crypto/openssl/crypto/err/err.h
crypto/openssl/crypto/err/err_all.c
crypto/openssl/crypto/evp/bio_md.c
crypto/openssl/crypto/evp/bio_ok.c
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 [new file with mode: 0644]
crypto/openssl/crypto/evp/e_des3.c
crypto/openssl/crypto/evp/e_null.c
crypto/openssl/crypto/evp/e_old.c [copied from crypto/openssl/crypto/ec/ec_cvt.c with 53% similarity]
crypto/openssl/crypto/evp/e_rc2.c
crypto/openssl/crypto/evp/e_rc4.c
crypto/openssl/crypto/evp/e_rc4_hmac_md5.c [new file with mode: 0644]
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 [new file with mode: 0644]
crypto/openssl/crypto/evp/evp_key.c
crypto/openssl/crypto/evp/evp_lib.c
crypto/openssl/crypto/evp/evp_locl.h
crypto/openssl/crypto/evp/evp_pbe.c
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_md4.c
crypto/openssl/crypto/evp/m_md5.c
crypto/openssl/crypto/evp/m_mdc2.c
crypto/openssl/crypto/evp/m_ripemd.c
crypto/openssl/crypto/evp/m_sha.c
crypto/openssl/crypto/evp/m_sha1.c
crypto/openssl/crypto/evp/m_wp.c
crypto/openssl/crypto/evp/names.c
crypto/openssl/crypto/evp/p5_crpt.c
crypto/openssl/crypto/evp/p5_crpt2.c
crypto/openssl/crypto/evp/p_open.c
crypto/openssl/crypto/evp/p_seal.c
crypto/openssl/crypto/evp/p_sign.c
crypto/openssl/crypto/evp/p_verify.c
crypto/openssl/crypto/evp/pmeth_gn.c
crypto/openssl/crypto/evp/pmeth_lib.c
crypto/openssl/crypto/fips_ers.c [new file with mode: 0644]
crypto/openssl/crypto/hmac/hm_ameth.c
crypto/openssl/crypto/hmac/hm_pmeth.c
crypto/openssl/crypto/hmac/hmac.c
crypto/openssl/crypto/idea/i_skey.c
crypto/openssl/crypto/idea/idea.h
crypto/openssl/crypto/md4/md4.h
crypto/openssl/crypto/md4/md4_dgst.c
crypto/openssl/crypto/md5/md5.h
crypto/openssl/crypto/md5/md5_dgst.c
crypto/openssl/crypto/mdc2/mdc2.h
crypto/openssl/crypto/mdc2/mdc2dgst.c
crypto/openssl/crypto/mem.c
crypto/openssl/crypto/modes/asm/ghash-x86.pl [new file with mode: 0644]
crypto/openssl/crypto/modes/asm/ghash-x86_64.pl [new file with mode: 0644]
crypto/openssl/crypto/modes/cbc128.c
crypto/openssl/crypto/modes/ccm128.c [new file with mode: 0644]
crypto/openssl/crypto/modes/cfb128.c
crypto/openssl/crypto/modes/ctr128.c
crypto/openssl/crypto/modes/cts128.c
crypto/openssl/crypto/modes/gcm128.c [new file with mode: 0644]
crypto/openssl/crypto/modes/modes.h
crypto/openssl/crypto/modes/modes_lcl.h [new file with mode: 0644]
crypto/openssl/crypto/modes/ofb128.c
crypto/openssl/crypto/modes/xts128.c [new file with mode: 0644]
crypto/openssl/crypto/o_fips.c [copied from crypto/openssl/crypto/dsa/dsa_locl.h with 75% similarity]
crypto/openssl/crypto/o_init.c [copied from crypto/openssl/crypto/aes/aes_misc.c with 76% similarity]
crypto/openssl/crypto/objects/obj_dat.h
crypto/openssl/crypto/objects/obj_mac.h
crypto/openssl/crypto/objects/obj_xref.c
crypto/openssl/crypto/objects/obj_xref.h
crypto/openssl/crypto/ocsp/ocsp_lib.c
crypto/openssl/crypto/opensslv.h
crypto/openssl/crypto/ossl_typ.h
crypto/openssl/crypto/pem/pvkfmt.c
crypto/openssl/crypto/perlasm/x86_64-xlate.pl
crypto/openssl/crypto/perlasm/x86asm.pl
crypto/openssl/crypto/perlasm/x86gas.pl
crypto/openssl/crypto/pkcs12/p12_decr.c
crypto/openssl/crypto/pkcs12/p12_key.c
crypto/openssl/crypto/pkcs12/p12_kiss.c
crypto/openssl/crypto/pkcs12/p12_mutl.c
crypto/openssl/crypto/pkcs7/pk7_doit.c
crypto/openssl/crypto/pkcs7/pk7_smime.c
crypto/openssl/crypto/rand/md_rand.c
crypto/openssl/crypto/rand/rand.h
crypto/openssl/crypto/rand/rand_err.c
crypto/openssl/crypto/rand/rand_lib.c
crypto/openssl/crypto/rc2/rc2.h
crypto/openssl/crypto/rc2/rc2_skey.c
crypto/openssl/crypto/rc4/asm/rc4-586.pl
crypto/openssl/crypto/rc4/asm/rc4-md5-x86_64.pl [new file with mode: 0644]
crypto/openssl/crypto/rc4/asm/rc4-x86_64.pl
crypto/openssl/crypto/rc4/rc4.h
crypto/openssl/crypto/rc4/rc4_skey.c
crypto/openssl/crypto/rc4/rc4_utl.c [copied from crypto/openssl/crypto/aes/aes_misc.c with 87% similarity]
crypto/openssl/crypto/ripemd/ripemd.h
crypto/openssl/crypto/ripemd/rmd_dgst.c
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_crpt.c [copied from crypto/openssl/crypto/rsa/rsa_lib.c with 56% similarity]
crypto/openssl/crypto/rsa/rsa_err.c
crypto/openssl/crypto/rsa/rsa_gen.c
crypto/openssl/crypto/rsa/rsa_lib.c
crypto/openssl/crypto/rsa/rsa_oaep.c
crypto/openssl/crypto/rsa/rsa_pmeth.c
crypto/openssl/crypto/rsa/rsa_pss.c
crypto/openssl/crypto/rsa/rsa_sign.c
crypto/openssl/crypto/seed/seed.c
crypto/openssl/crypto/seed/seed.h
crypto/openssl/crypto/sha/asm/sha1-586.pl
crypto/openssl/crypto/sha/asm/sha1-x86_64.pl
crypto/openssl/crypto/sha/asm/sha256-586.pl
crypto/openssl/crypto/sha/asm/sha512-x86_64.pl
crypto/openssl/crypto/sha/sha.h
crypto/openssl/crypto/sha/sha1dgst.c
crypto/openssl/crypto/sha/sha256.c
crypto/openssl/crypto/sha/sha512.c
crypto/openssl/crypto/sha/sha_dgst.c
crypto/openssl/crypto/sha/sha_locl.h
crypto/openssl/crypto/srp/srp.h [copied from crypto/openssl/crypto/ecdh/ecdh.h with 50% similarity]
crypto/openssl/crypto/srp/srp_grps.h [new file with mode: 0644]
crypto/openssl/crypto/srp/srp_lcl.h [copied from crypto/openssl/crypto/ecdh/ech_locl.h with 77% similarity]
crypto/openssl/crypto/srp/srp_lib.c [new file with mode: 0644]
crypto/openssl/crypto/srp/srp_vfy.c [new file with mode: 0644]
crypto/openssl/crypto/stack/safestack.h
crypto/openssl/crypto/symhacks.h
crypto/openssl/crypto/ts/ts.h
crypto/openssl/crypto/ts/ts_rsp_verify.c
crypto/openssl/crypto/ui/ui.h
crypto/openssl/crypto/ui/ui_openssl.c
crypto/openssl/crypto/whrlpool/whrlpool.h
crypto/openssl/crypto/whrlpool/wp_block.c
crypto/openssl/crypto/whrlpool/wp_dgst.c
crypto/openssl/crypto/x509/x509.h
crypto/openssl/crypto/x509/x509_cmp.c
crypto/openssl/crypto/x509/x509_vfy.c
crypto/openssl/crypto/x509/x509type.c
crypto/openssl/crypto/x509/x_all.c
crypto/openssl/crypto/x509v3/v3_asid.c
crypto/openssl/crypto/x509v3/v3_skey.c
crypto/openssl/crypto/x86_64cpuid.pl
crypto/openssl/crypto/x86cpuid.pl
crypto/openssl/doc/apps/genpkey.pod
crypto/openssl/doc/apps/openssl.pod
crypto/openssl/doc/ssl/SSL_alert_type_string.pod
crypto/openssl/e_os.h
crypto/openssl/e_os2.h
crypto/openssl/engines/ccgost/gost_ameth.c
crypto/openssl/engines/ccgost/gost_pmeth.c
crypto/openssl/engines/e_aep.c
crypto/openssl/engines/e_capi.c
crypto/openssl/engines/e_padlock.c
crypto/openssl/ssl/d1_both.c
crypto/openssl/ssl/d1_clnt.c
crypto/openssl/ssl/d1_lib.c
crypto/openssl/ssl/d1_pkt.c
crypto/openssl/ssl/d1_srtp.c [new file with mode: 0644]
crypto/openssl/ssl/d1_srvr.c
crypto/openssl/ssl/dtls1.h
crypto/openssl/ssl/kssl.c
crypto/openssl/ssl/kssl.h
crypto/openssl/ssl/s23_clnt.c
crypto/openssl/ssl/s23_meth.c
crypto/openssl/ssl/s23_srvr.c
crypto/openssl/ssl/s3_both.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 [copied from crypto/openssl/crypto/evp/m_ecdsa.c with 86% similarity]
crypto/openssl/ssl/ssl.h
crypto/openssl/ssl/ssl2.h
crypto/openssl/ssl/ssl3.h
crypto/openssl/ssl/ssl_algs.c
crypto/openssl/ssl/ssl_asn1.c
crypto/openssl/ssl/ssl_cert.c
crypto/openssl/ssl/ssl_ciph.c
crypto/openssl/ssl/ssl_err.c
crypto/openssl/ssl/ssl_lib.c
crypto/openssl/ssl/ssl_locl.h
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_lib.c
crypto/openssl/ssl/t1_meth.c
crypto/openssl/ssl/t1_srvr.c
crypto/openssl/ssl/tls1.h
crypto/openssl/ssl/tls_srp.c [new file with mode: 0644]

index 67ff293..03d7314 100644 (file)
@@ -2,6 +2,296 @@
  OpenSSL CHANGES
  _______________
 
+ Changes between 1.0.0h and 1.0.1  [14 Mar 2012]
+
+  *) Add compatibility with old MDC2 signatures which use an ASN1 OCTET
+     STRING form instead of a DigestInfo.
+     [Steve Henson]
+
+  *) The format used for MDC2 RSA signatures is inconsistent between EVP
+     and the RSA_sign/RSA_verify functions. This was made more apparent when
+     OpenSSL used RSA_sign/RSA_verify for some RSA signatures in particular
+     those which went through EVP_PKEY_METHOD in 1.0.0 and later. Detect 
+     the correct format in RSA_verify so both forms transparently work.
+     [Steve Henson]
+
+  *) Some servers which support TLS 1.0 can choke if we initially indicate
+     support for TLS 1.2 and later renegotiate using TLS 1.0 in the RSA
+     encrypted premaster secret. As a workaround use the maximum pemitted
+     client version in client hello, this should keep such servers happy
+     and still work with previous versions of OpenSSL.
+     [Steve Henson]
+
+  *) Add support for TLS/DTLS heartbeats.
+     [Robin Seggelmann <seggelmann@fh-muenster.de>]
+
+  *) Add support for SCTP.
+     [Robin Seggelmann <seggelmann@fh-muenster.de>]
+
+  *) Improved PRNG seeding for VOS.
+     [Paul Green <Paul.Green@stratus.com>]
+
+  *) Extensive assembler packs updates, most notably:
+
+       - x86[_64]:     AES-NI, PCLMULQDQ, RDRAND support;
+       - x86[_64]:     SSSE3 support (SHA1, vector-permutation AES);
+       - x86_64:       bit-sliced AES implementation;
+       - ARM:          NEON support, contemporary platforms optimizations;
+       - s390x:        z196 support;
+       - *:            GHASH and GF(2^m) multiplication implementations;
+
+     [Andy Polyakov]
+
+  *) Make TLS-SRP code conformant with RFC 5054 API cleanup
+     (removal of unnecessary code)
+     [Peter Sylvester <peter.sylvester@edelweb.fr>]
+
+  *) Add TLS key material exporter from RFC 5705.
+     [Eric Rescorla]
+
+  *) Add DTLS-SRTP negotiation from RFC 5764.
+     [Eric Rescorla]
+
+  *) Add Next Protocol Negotiation,
+     http://tools.ietf.org/html/draft-agl-tls-nextprotoneg-00. Can be
+     disabled with a no-npn flag to config or Configure. Code donated
+     by Google.
+     [Adam Langley <agl@google.com> and Ben Laurie]
+
+  *) Add optional 64-bit optimized implementations of elliptic curves NIST-P224,
+     NIST-P256, NIST-P521, with constant-time single point multiplication on
+     typical inputs. Compiler support for the nonstandard type __uint128_t is
+     required to use this (present in gcc 4.4 and later, for 64-bit builds).
+     Code made available under Apache License version 2.0.
+
+     Specify "enable-ec_nistp_64_gcc_128" on the Configure (or config) command
+     line to include this in your build of OpenSSL, and run "make depend" (or
+     "make update"). This enables the following EC_METHODs:
+
+         EC_GFp_nistp224_method()
+         EC_GFp_nistp256_method()
+         EC_GFp_nistp521_method()
+
+     EC_GROUP_new_by_curve_name() will automatically use these (while
+     EC_GROUP_new_curve_GFp() currently prefers the more flexible
+     implementations).
+     [Emilia K√§sper, Adam Langley, Bodo Moeller (Google)]
+
+  *) Use type ossl_ssize_t instad of ssize_t which isn't available on
+     all platforms. Move ssize_t definition from e_os.h to the public
+     header file e_os2.h as it now appears in public header file cms.h
+     [Steve Henson]
+
+  *) New -sigopt option to the ca, req and x509 utilities. Additional
+     signature parameters can be passed using this option and in
+     particular PSS. 
+     [Steve Henson]
+
+  *) Add RSA PSS signing function. This will generate and set the
+     appropriate AlgorithmIdentifiers for PSS based on those in the
+     corresponding EVP_MD_CTX structure. No application support yet.
+     [Steve Henson]
+
+  *) Support for companion algorithm specific ASN1 signing routines.
+     New function ASN1_item_sign_ctx() signs a pre-initialised
+     EVP_MD_CTX structure and sets AlgorithmIdentifiers based on
+     the appropriate parameters.
+     [Steve Henson]
+
+  *) Add new algorithm specific ASN1 verification initialisation function
+     to EVP_PKEY_ASN1_METHOD: this is not in EVP_PKEY_METHOD since the ASN1
+     handling will be the same no matter what EVP_PKEY_METHOD is used.
+     Add a PSS handler to support verification of PSS signatures: checked
+     against a number of sample certificates.
+     [Steve Henson]
+
+  *) Add signature printing for PSS. Add PSS OIDs.
+     [Steve Henson, Martin Kaiser <lists@kaiser.cx>]
+
+  *) Add algorithm specific signature printing. An individual ASN1 method
+     can now print out signatures instead of the standard hex dump. 
+
+     More complex signatures (e.g. PSS) can print out more meaningful
+     information. Include DSA version that prints out the signature
+     parameters r, s.
+     [Steve Henson]
+
+  *) Password based recipient info support for CMS library: implementing
+     RFC3211.
+     [Steve Henson]
+
+  *) Split password based encryption into PBES2 and PBKDF2 functions. This
+     neatly separates the code into cipher and PBE sections and is required
+     for some algorithms that split PBES2 into separate pieces (such as
+     password based CMS).
+     [Steve Henson]
+
+  *) Session-handling fixes:
+     - Fix handling of connections that are resuming with a session ID,
+       but also support Session Tickets.
+     - Fix a bug that suppressed issuing of a new ticket if the client
+       presented a ticket with an expired session.
+     - Try to set the ticket lifetime hint to something reasonable.
+     - Make tickets shorter by excluding irrelevant information.
+     - On the client side, don't ignore renewed tickets.
+     [Adam Langley, Bodo Moeller (Google)]
+
+  *) Fix PSK session representation.
+     [Bodo Moeller]
+
+  *) Add RC4-MD5 and AESNI-SHA1 "stitched" implementations.
+
+     This work was sponsored by Intel.
+     [Andy Polyakov]
+
+  *) Add GCM support to TLS library. Some custom code is needed to split
+     the IV between the fixed (from PRF) and explicit (from TLS record)
+     portions. This adds all GCM ciphersuites supported by RFC5288 and 
+     RFC5289. Generalise some AES* cipherstrings to inlclude GCM and
+     add a special AESGCM string for GCM only.
+     [Steve Henson]
+
+  *) Expand range of ctrls for AES GCM. Permit setting invocation
+     field on decrypt and retrieval of invocation field only on encrypt.
+     [Steve Henson]
+
+  *) Add HMAC ECC ciphersuites from RFC5289. Include SHA384 PRF support.
+     As required by RFC5289 these ciphersuites cannot be used if for
+     versions of TLS earlier than 1.2.
+     [Steve Henson]
+
+  *) For FIPS capable OpenSSL interpret a NULL default public key method
+     as unset and return the appopriate default but do *not* set the default.
+     This means we can return the appopriate method in applications that
+     swicth between FIPS and non-FIPS modes.
+     [Steve Henson]
+
+  *) Redirect HMAC and CMAC operations to FIPS module in FIPS mode. If an
+     ENGINE is used then we cannot handle that in the FIPS module so we
+     keep original code iff non-FIPS operations are allowed.
+     [Steve Henson]
+
+  *) Add -attime option to openssl utilities.
+     [Peter Eckersley <pde@eff.org>, Ben Laurie and Steve Henson]
+
+  *) Redirect DSA and DH operations to FIPS module in FIPS mode.
+     [Steve Henson]
+
+  *) Redirect ECDSA and ECDH operations to FIPS module in FIPS mode. Also use
+     FIPS EC methods unconditionally for now.
+     [Steve Henson]
+
+  *) New build option no-ec2m to disable characteristic 2 code.
+     [Steve Henson]
+
+  *) Backport libcrypto audit of return value checking from 1.1.0-dev; not
+     all cases can be covered as some introduce binary incompatibilities.
+     [Steve Henson]
+
+  *) Redirect RSA operations to FIPS module including keygen,
+     encrypt, decrypt, sign and verify. Block use of non FIPS RSA methods.
+     [Steve Henson]
+
+  *) Add similar low level API blocking to ciphers.
+     [Steve Henson]
+
+  *) Low level digest APIs are not approved in FIPS mode: any attempt
+     to use these will cause a fatal error. Applications that *really* want
+     to use them can use the private_* version instead.
+     [Steve Henson]
+
+  *) Redirect cipher operations to FIPS module for FIPS builds. 
+     [Steve Henson]
+
+  *) Redirect digest operations to FIPS module for FIPS builds. 
+     [Steve Henson]
+
+  *) Update build system to add "fips" flag which will link in fipscanister.o
+     for static and shared library builds embedding a signature if needed.
+     [Steve Henson]
+
+  *) Output TLS supported curves in preference order instead of numerical
+     order. This is currently hardcoded for the highest order curves first.
+     This should be configurable so applications can judge speed vs strength.
+     [Steve Henson]
+
+  *) Add TLS v1.2 server support for client authentication. 
+     [Steve Henson]
+
+  *) Add support for FIPS mode in ssl library: disable SSLv3, non-FIPS ciphers
+     and enable MD5.
+     [Steve Henson]
+
+  *) Functions FIPS_mode_set() and FIPS_mode() which call the underlying
+     FIPS modules versions.
+     [Steve Henson]
+
+  *) Add TLS v1.2 client side support for client authentication. Keep cache
+     of handshake records longer as we don't know the hash algorithm to use
+     until after the certificate request message is received.
+     [Steve Henson]
+
+  *) Initial TLS v1.2 client support. Add a default signature algorithms
+     extension including all the algorithms we support. Parse new signature
+     format in client key exchange. Relax some ECC signing restrictions for
+     TLS v1.2 as indicated in RFC5246.
+     [Steve Henson]
+
+  *) Add server support for TLS v1.2 signature algorithms extension. Switch
+     to new signature format when needed using client digest preference.
+     All server ciphersuites should now work correctly in TLS v1.2. No client
+     support yet and no support for client certificates.
+     [Steve Henson]
+
+  *) Initial TLS v1.2 support. Add new SHA256 digest to ssl code, switch
+     to SHA256 for PRF when using TLS v1.2 and later. Add new SHA256 based
+     ciphersuites. At present only RSA key exchange ciphersuites work with
+     TLS v1.2. Add new option for TLS v1.2 replacing the old and obsolete
+     SSL_OP_PKCS1_CHECK flags with SSL_OP_NO_TLSv1_2. New TLSv1.2 methods
+     and version checking.
+     [Steve Henson]
+
+  *) New option OPENSSL_NO_SSL_INTERN. If an application can be compiled
+     with this defined it will not be affected by any changes to ssl internal
+     structures. Add several utility functions to allow openssl application
+     to work with OPENSSL_NO_SSL_INTERN defined.
+     [Steve Henson]
+
+  *) Add SRP support.
+     [Tom Wu <tjw@cs.stanford.edu> and Ben Laurie]
+
+  *) Add functions to copy EVP_PKEY_METHOD and retrieve flags and id.
+     [Steve Henson]
+
+  *) Permit abbreviated handshakes when renegotiating using the function
+     SSL_renegotiate_abbreviated().
+     [Robin Seggelmann <seggelmann@fh-muenster.de>]
+
+  *) Add call to ENGINE_register_all_complete() to
+     ENGINE_load_builtin_engines(), so some implementations get used
+     automatically instead of needing explicit application support.
+     [Steve Henson]
+
+  *) Add support for TLS key exporter as described in RFC5705.
+     [Robin Seggelmann <seggelmann@fh-muenster.de>, Steve Henson]
+
+  *) Initial TLSv1.1 support. Since TLSv1.1 is very similar to TLS v1.0 only
+     a few changes are required:
+
+       Add SSL_OP_NO_TLSv1_1 flag.
+       Add TLSv1_1 methods.
+       Update version checking logic to handle version 1.1.
+       Add explicit IV handling (ported from DTLS code).
+       Add command line options to s_client/s_server.
+     [Steve Henson]
+
+ Changes between 1.0.0g and 1.0.0h [xx XXX xxxx]
+
+  *) Fix CVE-2011-4619: make sure we really are receiving a 
+     client hello before rejecting multiple SGC restarts. Thanks to
+     Ivan Nestlerode <inestlerode@us.ibm.com> for discovering this bug.
+     [Steve Henson]
+
  Changes between 1.0.0f and 1.0.0g [18 Jan 2012]
 
   *) Fix for DTLS DoS issue introduced by fix for CVE-2011-4109.
index 2a271ed..b9243a6 100644 (file)
@@ -82,7 +82,7 @@ OpenSSL  -  Frequently Asked Questions
 * Which is the current version of OpenSSL?
 
 The current version is available from <URL: http://www.openssl.org>.
-OpenSSL 1.0.0g was released on Jan 18th, 2012.
+OpenSSL 1.0.1 was released on Mar 14th, 2012.
 
 In addition to the current stable release, you can also access daily
 snapshots of the OpenSSL development version at <URL:
index 1264201..3db8ea9 100644 (file)
@@ -5,6 +5,25 @@
   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.0h and OpenSSL 1.0.1:
+
+      o TLS/DTLS heartbeat support.
+      o SCTP support.
+      o RFC 5705 TLS key material exporter.
+      o RFC 5764 DTLS-SRTP negotiation.
+      o Next Protocol Negotiation.
+      o PSS signatures in certificates, requests and CRLs.
+      o Support for password based recipient info for CMS.
+      o Support TLS v1.2 and TLS v1.1.
+      o Preliminary FIPS capability for unvalidated 2.0 FIPS module.
+      o SRP support.
+
+  Major changes between OpenSSL 1.0.0g and OpenSSL 1.0.0h:
+
+      o Fix for CMS/PKCS#7 MMA CVE-2012-0884
+      o Corrected fix for CVE-2011-4619
+      o Various DTLS fixes.
+
   Major changes between OpenSSL 1.0.0f and OpenSSL 1.0.0g:
 
       o Fix for DTLS DoS issue CVE-2012-0050
index 6144ddf..3a0456c 100644 (file)
@@ -1,5 +1,5 @@
 
- OpenSSL 1.0.0g 18 Jan 2012
+ OpenSSL 1.0.1 14 Mar 2012
 
  Copyright (c) 1998-2011 The OpenSSL Project
  Copyright (c) 1995-1998 Eric A. Young, Tim J. Hudson
index f44d5f1..4a7e232 100644 (file)
@@ -12,6 +12,7 @@ INSTALL.W64
 INSTALL.WCE
 MacOS/
 Makefile
+Makefile.bak
 Makefile.org
 Makefile.shared
 Netware/
@@ -25,6 +26,7 @@ apps/ca-req.pem
 apps/cert.pem
 apps/client.pem
 apps/demoCA/
+apps/demoSRP/
 apps/dh1024.pem
 apps/dh2048.pem
 apps/dh4096.pem
@@ -71,10 +73,15 @@ crypto/aes/Makefile
 crypto/aes/aes_x86core.c
 crypto/aes/asm/aes-armv4.pl
 crypto/aes/asm/aes-ia64.S
+crypto/aes/asm/aes-mips.pl
+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/alphacpuid.pl
+crypto/arm_arch.h
+crypto/armcap.c
+crypto/armv4cpuid.S
 crypto/asn1/Makefile
 crypto/asn1/charmap.pl
 crypto/bf/INSTALL
@@ -91,15 +98,21 @@ crypto/bio/bss_rtcp.c
 crypto/bn/Makefile
 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/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
 crypto/bn/asm/ppc-mont.pl
 crypto/bn/asm/ppc.pl
 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/sparcv8.S
@@ -127,6 +140,7 @@ crypto/cast/cast_spd.c
 crypto/cast/castopts.c
 crypto/cast/casts.cpp
 crypto/cast/casttest.c
+crypto/cmac/Makefile
 crypto/cms/Makefile
 crypto/comp/Makefile
 crypto/conf/Makefile
@@ -190,9 +204,9 @@ crypto/err/Makefile
 crypto/err/openssl.ec
 crypto/evp/Makefile
 crypto/evp/e_dsa.c
-crypto/evp/e_old.c
 crypto/evp/evp_test.c
 crypto/evp/evptests.txt
+crypto/fips_err.h
 crypto/hmac/Makefile
 crypto/hmac/hmactest.c
 crypto/ia64cpuid.S
@@ -218,6 +232,12 @@ crypto/md5/md5test.c
 crypto/mdc2/Makefile
 crypto/mdc2/mdc2test.c
 crypto/modes/Makefile
+crypto/modes/asm/ghash-alpha.pl
+crypto/modes/asm/ghash-armv4.pl
+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/o_dir_test.c
 crypto/o_str.c
 crypto/o_str.h
@@ -231,6 +251,7 @@ crypto/objects/objxref.pl
 crypto/ocsp/Makefile
 crypto/opensslconf.h
 crypto/opensslconf.h.in
+crypto/pariscid.pl
 crypto/pem/Makefile
 crypto/pem/pkcs7.lis
 crypto/perlasm/ppc-xlate.pl
@@ -253,6 +274,7 @@ crypto/pkcs7/server.pem
 crypto/pkcs7/sign.c
 crypto/pkcs7/t/
 crypto/pkcs7/verify.c
+crypto/ppccap.c
 crypto/ppccpuid.pl
 crypto/pqueue/Makefile
 crypto/rand/Makefile
@@ -267,6 +289,7 @@ crypto/rc2/rrc2.doc
 crypto/rc2/tab.c
 crypto/rc4/Makefile
 crypto/rc4/asm/rc4-ia64.pl
+crypto/rc4/asm/rc4-parisc.pl
 crypto/rc4/asm/rc4-s390x.pl
 crypto/rc4/rc4.c
 crypto/rc4/rc4s.cpp
@@ -285,8 +308,11 @@ crypto/s390xcpuid.S
 crypto/seed/Makefile
 crypto/sha/Makefile
 crypto/sha/asm/README
+crypto/sha/asm/sha1-alpha.pl
 crypto/sha/asm/sha1-armv4-large.pl
 crypto/sha/asm/sha1-ia64.pl
+crypto/sha/asm/sha1-mips.pl
+crypto/sha/asm/sha1-parisc.pl
 crypto/sha/asm/sha1-ppc.pl
 crypto/sha/asm/sha1-s390x.pl
 crypto/sha/asm/sha1-sparcv9.pl
@@ -295,6 +321,8 @@ crypto/sha/asm/sha1-thumb.pl
 crypto/sha/asm/sha256-armv4.pl
 crypto/sha/asm/sha512-armv4.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
@@ -306,6 +334,8 @@ crypto/sha/sha512t.c
 crypto/sha/shatest.c
 crypto/sparccpuid.S
 crypto/sparcv9cap.c
+crypto/srp/Makefile
+crypto/srp/srptest.c
 crypto/stack/Makefile
 crypto/store/
 crypto/threads/mttest.c
index feb7ed4..4e11915 100644 (file)
  *
  */
 
-#ifndef _POSIX_C_SOURCE
+#if !defined(_POSIX_C_SOURCE) && defined(OPENSSL_SYS_VMS)
 #define _POSIX_C_SOURCE 2      /* On VMS, you need to define this to get
                                   the declaration of fileno().  The value
                                   2 is to make sure no function defined
@@ -1215,7 +1215,8 @@ STACK_OF(X509) *load_certs(BIO *err, const char *file, int format,
        const char *pass, ENGINE *e, const char *desc)
        {
        STACK_OF(X509) *certs;
-       load_certs_crls(err, file, format, pass, e, desc, &certs, NULL);
+       if (!load_certs_crls(err, file, format, pass, e, desc, &certs, NULL))
+               return NULL;
        return certs;
        }       
 
@@ -1223,7 +1224,8 @@ STACK_OF(X509_CRL) *load_crls(BIO *err, const char *file, int format,
        const char *pass, ENGINE *e, const char *desc)
        {
        STACK_OF(X509_CRL) *crls;
-       load_certs_crls(err, file, format, pass, e, desc, NULL, &crls);
+       if (!load_certs_crls(err, file, format, pass, e, desc, NULL, &crls))
+               return NULL;
        return crls;
        }       
 
@@ -2256,6 +2258,7 @@ int args_verify(char ***pargs, int *pargc,
        int purpose = 0, depth = -1;
        char **oldargs = *pargs;
        char *arg = **pargs, *argn = (*pargs)[1];
+       time_t at_time = 0;
        if (!strcmp(arg, "-policy"))
                {
                if (!argn)
@@ -2308,6 +2311,27 @@ int args_verify(char ***pargs, int *pargc,
                        }
                (*pargs)++;
                }
+       else if (strcmp(arg,"-attime") == 0)
+               {
+               if (!argn)
+                       *badarg = 1;
+               else
+                       {
+                       long timestamp;
+                       /* interpret the -attime argument as seconds since
+                        * Epoch */
+                       if (sscanf(argn, "%li", &timestamp) != 1)
+                               {
+                               BIO_printf(bio_err,
+                                               "Error parsing timestamp %s\n",
+                                               argn);
+                               *badarg = 1;
+                               }
+                       /* on some platforms time_t may be a float */
+                       at_time = (time_t) timestamp;
+                       }
+               (*pargs)++;
+               }
        else if (!strcmp(arg, "-ignore_critical"))
                flags |= X509_V_FLAG_IGNORE_CRITICAL;
        else if (!strcmp(arg, "-issuer_checks"))
@@ -2362,6 +2386,9 @@ int args_verify(char ***pargs, int *pargc,
        if (depth >= 0)
                X509_VERIFY_PARAM_set_depth(*pm, depth);
 
+       if (at_time) 
+               X509_VERIFY_PARAM_set_time(*pm, at_time);
+
        end:
 
        (*pargs)++;
@@ -2693,6 +2720,50 @@ void jpake_server_auth(BIO *out, BIO *conn, const char *secret)
 
 #endif
 
+#if !defined(OPENSSL_NO_TLSEXT) && !defined(OPENSSL_NO_NEXTPROTONEG)
+/* 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.
+ *   outlen: (output) set to the length of the resulting buffer on success.
+ *   err: (maybe NULL) on failure, an error message line is written to this BIO.
+ *   in: a NUL termianted string like "abc,def,ghi"
+ *
+ *   returns: a malloced buffer or NULL on failure.
+ */
+unsigned char *next_protos_parse(unsigned short *outlen, const char *in)
+       {
+       size_t len;
+       unsigned char *out;
+       size_t i, start = 0;
+
+       len = strlen(in);
+       if (len >= 65535)
+               return NULL;
+
+       out = OPENSSL_malloc(strlen(in) + 1);
+       if (!out)
+               return NULL;
+
+       for (i = 0; i <= len; ++i)
+               {
+               if (i == len || in[i] == ',')
+                       {
+                       if (i - start > 255)
+                               {
+                               OPENSSL_free(out);
+                               return NULL;
+                               }
+                       out[start] = i - start;
+                       start = i + 1;
+                       }
+               else
+                       out[i+1] = in[i];
+               }
+
+       *outlen = len + 1;
+       return out;
+       }
+#endif  /* !OPENSSL_NO_TLSEXT && !OPENSSL_NO_NEXTPROTONEG */
+
 /*
  * Platform-specific sections
  */
index 596a39a..c1ca99d 100644 (file)
@@ -317,6 +317,12 @@ int bio_to_mem(unsigned char **out, int maxlen, BIO *in);
 int pkey_ctrl_string(EVP_PKEY_CTX *ctx, 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,
+                       STACK_OF(OPENSSL_STRING) *sigopts);
+int do_X509_REQ_sign(BIO *err, X509_REQ *x, EVP_PKEY *pkey, const EVP_MD *md,
+                       STACK_OF(OPENSSL_STRING) *sigopts);
+int do_X509_CRL_sign(BIO *err, X509_CRL *x, EVP_PKEY *pkey, const EVP_MD *md,
+                       STACK_OF(OPENSSL_STRING) *sigopts);
 #ifndef OPENSSL_NO_PSK
 extern char *psk_key;
 #endif
@@ -325,6 +331,10 @@ 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)
+unsigned char *next_protos_parse(unsigned short *outlen, const char *in);
+#endif  /* !OPENSSL_NO_TLSEXT && !OPENSSL_NO_NEXTPROTONEG */
+
 #define FORMAT_UNDEF    0
 #define FORMAT_ASN1     1
 #define FORMAT_TEXT     2
@@ -357,4 +367,7 @@ int raw_write_stdout(const void *,int);
 #define TM_START       0
 #define TM_STOP                1
 double app_tminterval (int stop,int usertime);
+
+#define OPENSSL_NO_SSL_INTERN
+
 #endif
index 5d11948..2a83d19 100644 (file)
@@ -197,26 +197,30 @@ extern int EF_ALIGNMENT;
 
 static void lookup_fail(const char *name, const char *tag);
 static int certify(X509 **xret, char *infile,EVP_PKEY *pkey,X509 *x509,
-                  const EVP_MD *dgst,STACK_OF(CONF_VALUE) *policy,CA_DB *db,
+                  const EVP_MD *dgst,STACK_OF(OPENSSL_STRING) *sigopts,
+                  STACK_OF(CONF_VALUE) *policy,CA_DB *db,
                   BIGNUM *serial, char *subj,unsigned long chtype, int multirdn, int email_dn, char *startdate,
                   char *enddate, long days, int batch, char *ext_sect, CONF *conf,
                   int verbose, unsigned long certopt, unsigned long nameopt,
                   int default_op, int ext_copy, int selfsign);
 static int certify_cert(X509 **xret, char *infile,EVP_PKEY *pkey,X509 *x509,
-                       const EVP_MD *dgst,STACK_OF(CONF_VALUE) *policy,
+                       const EVP_MD *dgst,STACK_OF(OPENSSL_STRING) *sigopts,
+                       STACK_OF(CONF_VALUE) *policy,
                        CA_DB *db, BIGNUM *serial, char *subj,unsigned long chtype, int multirdn, int email_dn,
                        char *startdate, char *enddate, long days, int batch,
                        char *ext_sect, CONF *conf,int verbose, unsigned long certopt,
                        unsigned long nameopt, int default_op, int ext_copy,
                        ENGINE *e);
 static int certify_spkac(X509 **xret, char *infile,EVP_PKEY *pkey,X509 *x509,
-                        const EVP_MD *dgst,STACK_OF(CONF_VALUE) *policy,
+                        const EVP_MD *dgst,STACK_OF(OPENSSL_STRING) *sigopts,
+                        STACK_OF(CONF_VALUE) *policy,
                         CA_DB *db, BIGNUM *serial,char *subj,unsigned long chtype, int multirdn, int email_dn,
                         char *startdate, char *enddate, long days, char *ext_sect,
                         CONF *conf, int verbose, unsigned long certopt, 
                         unsigned long nameopt, int default_op, int ext_copy);
 static void write_new_certificate(BIO *bp, X509 *x, int output_der, int notext);
 static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509, const EVP_MD *dgst,
+       STACK_OF(OPENSSL_STRING) *sigopts,
        STACK_OF(CONF_VALUE) *policy, CA_DB *db, BIGNUM *serial,char *subj,unsigned long chtype, int multirdn,
        int email_dn, char *startdate, char *enddate, long days, int batch,
                int verbose, X509_REQ *req, char *ext_sect, CONF *conf,
@@ -311,6 +315,7 @@ int MAIN(int argc, char **argv)
        const EVP_MD *dgst=NULL;
        STACK_OF(CONF_VALUE) *attribs=NULL;
        STACK_OF(X509) *cert_sk=NULL;
+       STACK_OF(OPENSSL_STRING) *sigopts = NULL;
 #undef BSIZE
 #define BSIZE 256
        MS_STATIC char buf[3][BSIZE];
@@ -435,6 +440,15 @@ EF_ALIGNMENT=0;
                        if (--argc < 1) goto bad;
                        outdir= *(++argv);
                        }
+               else if (strcmp(*argv,"-sigopt") == 0)
+                       {
+                       if (--argc < 1)
+                               goto bad;
+                       if (!sigopts)
+                               sigopts = sk_OPENSSL_STRING_new_null();
+                       if (!sigopts || !sk_OPENSSL_STRING_push(sigopts, *(++argv)))
+                               goto bad;
+                       }
                else if (strcmp(*argv,"-notext") == 0)
                        notext=1;
                else if (strcmp(*argv,"-batch") == 0)
@@ -1170,8 +1184,9 @@ bad:
                if (spkac_file != NULL)
                        {
                        total++;
-                       j=certify_spkac(&x,spkac_file,pkey,x509,dgst,attribs,db,
-                               serial,subj,chtype,multirdn,email_dn,startdate,enddate,days,extensions,
+                       j=certify_spkac(&x,spkac_file,pkey,x509,dgst,sigopts,
+                               attribs,db, serial,subj,chtype,multirdn,
+                               email_dn,startdate,enddate,days,extensions,
                                conf,verbose,certopt,nameopt,default_op,ext_copy);
                        if (j < 0) goto err;
                        if (j > 0)
@@ -1194,7 +1209,8 @@ bad:
                if (ss_cert_file != NULL)
                        {
                        total++;
-                       j=certify_cert(&x,ss_cert_file,pkey,x509,dgst,attribs,
+                       j=certify_cert(&x,ss_cert_file,pkey,x509,dgst,sigopts,
+                               attribs,
                                db,serial,subj,chtype,multirdn,email_dn,startdate,enddate,days,batch,
                                extensions,conf,verbose, certopt, nameopt,
                                default_op, ext_copy, e);
@@ -1214,7 +1230,7 @@ bad:
                if (infile != NULL)
                        {
                        total++;
-                       j=certify(&x,infile,pkey,x509p,dgst,attribs,db,
+                       j=certify(&x,infile,pkey,x509p,dgst,sigopts, attribs,db,
                                serial,subj,chtype,multirdn,email_dn,startdate,enddate,days,batch,
                                extensions,conf,verbose, certopt, nameopt,
                                default_op, ext_copy, selfsign);
@@ -1234,7 +1250,7 @@ bad:
                for (i=0; i<argc; i++)
                        {
                        total++;
-                       j=certify(&x,argv[i],pkey,x509p,dgst,attribs,db,
+                       j=certify(&x,argv[i],pkey,x509p,dgst,sigopts,attribs,db,
                                serial,subj,chtype,multirdn,email_dn,startdate,enddate,days,batch,
                                extensions,conf,verbose, certopt, nameopt,
                                default_op, ext_copy, selfsign);
@@ -1483,7 +1499,7 @@ bad:
                        crlnumber = NULL;
                        }
 
-               if (!X509_CRL_sign(crl,pkey,dgst)) goto err;
+               if (!do_X509_CRL_sign(bio_err,crl,pkey,dgst,sigopts)) goto err;
 
                PEM_write_bio_X509_CRL(Sout,crl);
 
@@ -1537,6 +1553,8 @@ err:
        BN_free(serial);
        BN_free(crlnumber);
        free_index(db);
+       if (sigopts)
+               sk_OPENSSL_STRING_free(sigopts);
        EVP_PKEY_free(pkey);
        if (x509) X509_free(x509);
        X509_CRL_free(crl);
@@ -1553,8 +1571,10 @@ static void lookup_fail(const char *name, const char *tag)
        }
 
 static int certify(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509,
-            const EVP_MD *dgst, STACK_OF(CONF_VALUE) *policy, CA_DB *db,
-            BIGNUM *serial, char *subj,unsigned long chtype, int multirdn, int email_dn, char *startdate, char *enddate,
+            const EVP_MD *dgst, STACK_OF(OPENSSL_STRING) *sigopts,
+            STACK_OF(CONF_VALUE) *policy, CA_DB *db,
+            BIGNUM *serial, char *subj,unsigned long chtype, int multirdn,
+            int email_dn, char *startdate, char *enddate,
             long days, int batch, char *ext_sect, CONF *lconf, int verbose,
             unsigned long certopt, unsigned long nameopt, int default_op,
             int ext_copy, int selfsign)
@@ -1610,7 +1630,8 @@ static int certify(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509,
        else
                BIO_printf(bio_err,"Signature ok\n");
 
-       ok=do_body(xret,pkey,x509,dgst,policy,db,serial,subj,chtype,multirdn, email_dn,
+       ok=do_body(xret,pkey,x509,dgst,sigopts, policy,db,serial,subj,chtype,
+               multirdn, email_dn,
                startdate,enddate,days,batch,verbose,req,ext_sect,lconf,
                certopt, nameopt, default_op, ext_copy, selfsign);
 
@@ -1621,7 +1642,8 @@ err:
        }
 
 static int certify_cert(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509,
-            const EVP_MD *dgst, STACK_OF(CONF_VALUE) *policy, CA_DB *db,
+            const EVP_MD *dgst, STACK_OF(OPENSSL_STRING) *sigopts,
+            STACK_OF(CONF_VALUE) *policy, CA_DB *db,
             BIGNUM *serial, char *subj, unsigned long chtype, int multirdn, int email_dn, char *startdate, char *enddate,
             long days, int batch, char *ext_sect, CONF *lconf, int verbose,
             unsigned long certopt, unsigned long nameopt, int default_op,
@@ -1664,7 +1686,7 @@ static int certify_cert(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509,
        if ((rreq=X509_to_X509_REQ(req,NULL,EVP_md5())) == NULL)
                goto err;
 
-       ok=do_body(xret,pkey,x509,dgst,policy,db,serial,subj,chtype,multirdn,email_dn,startdate,enddate,
+       ok=do_body(xret,pkey,x509,dgst,sigopts,policy,db,serial,subj,chtype,multirdn,email_dn,startdate,enddate,
                days,batch,verbose,rreq,ext_sect,lconf, certopt, nameopt, default_op,
                ext_copy, 0);
 
@@ -1675,7 +1697,8 @@ err:
        }
 
 static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509, const EVP_MD *dgst,
-            STACK_OF(CONF_VALUE) *policy, CA_DB *db, BIGNUM *serial, char *subj,
+            STACK_OF(OPENSSL_STRING) *sigopts, STACK_OF(CONF_VALUE) *policy,
+             CA_DB *db, BIGNUM *serial, char *subj,
             unsigned long chtype, int multirdn,
             int email_dn, char *startdate, char *enddate, long days, int batch,
             int verbose, X509_REQ *req, char *ext_sect, CONF *lconf,
@@ -2146,7 +2169,7 @@ again2:
                EVP_PKEY_copy_parameters(pktmp,pkey);
        EVP_PKEY_free(pktmp);
 
-       if (!X509_sign(ret,pkey,dgst))
+       if (!do_X509_sign(bio_err, ret,pkey,dgst, sigopts))
                goto err;
 
        /* We now just add it to the database */
@@ -2240,7 +2263,8 @@ static void write_new_certificate(BIO *bp, X509 *x, int output_der, int notext)
        }
 
 static int certify_spkac(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509,
-            const EVP_MD *dgst, STACK_OF(CONF_VALUE) *policy, CA_DB *db,
+            const EVP_MD *dgst, STACK_OF(OPENSSL_STRING) *sigopts,
+            STACK_OF(CONF_VALUE) *policy, CA_DB *db,
             BIGNUM *serial, char *subj,unsigned long chtype, int multirdn, int email_dn, char *startdate, char *enddate,
             long days, char *ext_sect, CONF *lconf, int verbose, unsigned long certopt,
             unsigned long nameopt, int default_op, int ext_copy)
@@ -2366,9 +2390,9 @@ static int certify_spkac(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509,
 
        X509_REQ_set_pubkey(req,pktmp);
        EVP_PKEY_free(pktmp);
-       ok=do_body(xret,pkey,x509,dgst,policy,db,serial,subj,chtype,multirdn,email_dn,startdate,enddate,
-                  days,1,verbose,req,ext_sect,lconf, certopt, nameopt, default_op,
-                       ext_copy, 0);
+       ok=do_body(xret,pkey,x509,dgst,sigopts,policy,db,serial,subj,chtype,
+                  multirdn,email_dn,startdate,enddate, days,1,verbose,req,
+                  ext_sect,lconf, certopt, nameopt, default_op, ext_copy, 0);
 err:
        if (req != NULL) X509_REQ_free(req);
        if (parms != NULL) CONF_free(parms);
index 3d4c60d..5f2b739 100644 (file)
@@ -196,7 +196,7 @@ int MAIN(int argc, char **argv)
                        
                        if (Verbose)
                                {
-                               unsigned long id = c->id;
+                               unsigned long id = SSL_CIPHER_get_id(c);
                                int id0 = (int)(id >> 24);
                                int id1 = (int)((id >> 16) & 0xffL);
                                int id2 = (int)((id >> 8) & 0xffL);
index d15925a..d754140 100644 (file)
@@ -136,6 +136,7 @@ int MAIN(int argc, char **argv)
        char *engine=NULL;
 #endif
        unsigned char *secret_key = NULL, *secret_keyid = NULL;
+       unsigned char *pwri_pass = NULL, *pwri_tmp = NULL;
        size_t secret_keylen = 0, secret_keyidlen = 0;
 
        ASN1_OBJECT *econtent_type = NULL;
@@ -326,6 +327,13 @@ int MAIN(int argc, char **argv)
                                }
                        secret_keyidlen = (size_t)ltmp;
                        }
+               else if (!strcmp(*args,"-pwri_password"))
+                       {
+                       if (!args[1])
+                               goto argerr;
+                       args++;
+                       pwri_pass = (unsigned char *)*args;
+                       }
                else if (!strcmp(*args,"-econtent_type"))
                        {
                        if (!args[1])
@@ -559,7 +567,7 @@ int MAIN(int argc, char **argv)
 
        else if (operation == SMIME_DECRYPT)
                {
-               if (!recipfile && !keyfile && !secret_key)
+               if (!recipfile && !keyfile && !secret_key && !pwri_pass)
                        {
                        BIO_printf(bio_err, "No recipient certificate or key specified\n");
                        badarg = 1;
@@ -567,7 +575,7 @@ int MAIN(int argc, char **argv)
                }
        else if (operation == SMIME_ENCRYPT)
                {
-               if (!*args && !secret_key)
+               if (!*args && !secret_key && !pwri_pass)
                        {
                        BIO_printf(bio_err, "No recipient(s) certificate(s) specified\n");
                        badarg = 1;
@@ -917,6 +925,17 @@ int MAIN(int argc, char **argv)
                        secret_key = NULL;
                        secret_keyid = NULL;
                        }
+               if (pwri_pass)
+                       {
+                       pwri_tmp = (unsigned char *)BUF_strdup((char *)pwri_pass);
+                       if (!pwri_tmp)
+                               goto end;
+                       if (!CMS_add0_recipient_password(cms,
+                                               -1, NID_undef, NID_undef,
+                                                pwri_tmp, -1, NULL))
+                               goto end;
+                       pwri_tmp = NULL;
+                       }
                if (!(flags & CMS_STREAM))
                        {
                        if (!CMS_final(cms, in, NULL, flags))
@@ -1043,6 +1062,16 @@ int MAIN(int argc, char **argv)
                                }
                        }
 
+               if (pwri_pass)
+                       {
+                       if (!CMS_decrypt_set1_password(cms, pwri_pass, -1))
+                               {
+                               BIO_puts(bio_err,
+                                       "Error decrypting CMS using password\n");
+                               goto end;
+                               }
+                       }
+
                if (!CMS_decrypt(cms, NULL, NULL, indata, out, flags))
                        {
                        BIO_printf(bio_err, "Error decrypting CMS structure\n");
@@ -1167,6 +1196,8 @@ end:
                OPENSSL_free(secret_key);
        if (secret_keyid)
                OPENSSL_free(secret_keyid);
+       if (pwri_tmp)
+               OPENSSL_free(pwri_tmp);
        if (econtent_type)
                ASN1_OBJECT_free(econtent_type);
        if (rr)
index 9bf38ce..b08e9a7 100644 (file)
@@ -127,6 +127,7 @@ int MAIN(int argc, char **argv)
 #endif
        char *hmac_key=NULL;
        char *mac_name=NULL;
+       int non_fips_allow = 0;
        STACK_OF(OPENSSL_STRING) *sigopts = NULL, *macopts = NULL;
 
        apps_startup();
@@ -215,6 +216,10 @@ int MAIN(int argc, char **argv)
                        out_bin = 1;
                else if (strcmp(*argv,"-d") == 0)
                        debug=1;
+               else if (strcmp(*argv,"-non-fips-allow") == 0)
+                       non_fips_allow=1;
+               else if (!strcmp(*argv,"-fips-fingerprint"))
+                       hmac_key = "etaonrishdlcupfm";
                else if (!strcmp(*argv,"-hmac"))
                        {
                        if (--argc < 1)
@@ -395,6 +400,13 @@ int MAIN(int argc, char **argv)
                        goto end;
                }
 
+       if (non_fips_allow)
+               {
+               EVP_MD_CTX *md_ctx;
+               BIO_get_md_ctx(bmd,&md_ctx);
+               EVP_MD_CTX_set_flags(md_ctx, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW);
+               }
+
        if (hmac_key)
                {
                sigkey = EVP_PKEY_new_mac_key(EVP_PKEY_HMAC, e,
index 076225c..719acc3 100644 (file)
@@ -129,6 +129,7 @@ int MAIN(int argc, char **argv)
        char *engine = NULL;
 #endif
        const EVP_MD *dgst=NULL;
+       int non_fips_allow = 0;
 
        apps_startup();
 
@@ -281,6 +282,8 @@ int MAIN(int argc, char **argv)
                        if (--argc < 1) goto bad;
                        md= *(++argv);
                        }
+               else if (strcmp(*argv,"-non-fips-allow") == 0)
+                       non_fips_allow = 1;
                else if ((argv[0][0] == '-') &&
                        ((c=EVP_get_cipherbyname(&(argv[0][1]))) != NULL))
                        {
@@ -589,6 +592,11 @@ bad:
                 */
 
                BIO_get_cipher_ctx(benc, &ctx);
+
+               if (non_fips_allow)
+                       EVP_CIPHER_CTX_set_flags(ctx,
+                               EVP_CIPH_FLAG_NON_FIPS_ALLOW);
+
                if (!EVP_CipherInit_ex(ctx, cipher, NULL, NULL, NULL, enc))
                        {
                        BIO_printf(bio_err, "Error setting cipher %s\n",
index dab057b..1c880d9 100644 (file)
 #include "progs.h"
 #include "s_apps.h"
 #include <openssl/err.h>
+#ifdef OPENSSL_FIPS
+#include <openssl/fips.h>
+#endif
 
 /* The LHASH callbacks ("hash" & "cmp") have been replaced by functions with the
  * base prototypes (we cast each variable inside the function to the required
@@ -310,6 +313,19 @@ int main(int Argc, char *ARGV[])
                CRYPTO_set_locking_callback(lock_dbg_cb);
                }
 
+       if(getenv("OPENSSL_FIPS")) {
+#ifdef OPENSSL_FIPS
+               if (!FIPS_mode_set(1)) {
+                       ERR_load_crypto_strings();
+                       ERR_print_errors(BIO_new_fp(stderr,BIO_NOCLOSE));
+                       EXIT(1);
+               }
+#else
+               fprintf(stderr, "FIPS mode not supported.\n");
+               EXIT(1);
+#endif
+               }
+
        apps_startup();
 
        /* Lets load up our environment a little */
index 79e479a..949e780 100644 (file)
@@ -46,6 +46,7 @@ extern int engine_main(int argc,char *argv[]);
 extern int ocsp_main(int argc,char *argv[]);
 extern int prime_main(int argc,char *argv[]);
 extern int ts_main(int argc,char *argv[]);
+extern int srp_main(int argc,char *argv[]);
 
 #define FUNC_TYPE_GENERAL      1
 #define FUNC_TYPE_MD           2
@@ -147,6 +148,9 @@ FUNCTION functions[] = {
 #endif
        {FUNC_TYPE_GENERAL,"prime",prime_main},
        {FUNC_TYPE_GENERAL,"ts",ts_main},
+#ifndef OPENSSL_NO_SRP
+       {FUNC_TYPE_GENERAL,"srp",srp_main},
+#endif
 #ifndef OPENSSL_NO_MD2
        {FUNC_TYPE_MD,"md2",dgst_main},
 #endif
index 820cd18..8552658 100644 (file)
@@ -165,7 +165,7 @@ int MAIN(int argc, char **argv)
        EVP_PKEY_CTX *genctx = NULL;
        const char *keyalg = NULL;
        char *keyalgstr = NULL;
-       STACK_OF(OPENSSL_STRING) *pkeyopts = NULL;
+       STACK_OF(OPENSSL_STRING) *pkeyopts = NULL, *sigopts = NULL;
        EVP_PKEY *pkey=NULL;
        int i=0,badops=0,newreq=0,verbose=0,pkey_type=-1;
        long newkey = -1;
@@ -310,6 +310,15 @@ int MAIN(int argc, char **argv)
                        if (!pkeyopts || !sk_OPENSSL_STRING_push(pkeyopts, *(++argv)))
                                goto bad;
                        }
+               else if (strcmp(*argv,"-sigopt") == 0)
+                       {
+                       if (--argc < 1)
+                               goto bad;
+                       if (!sigopts)
+                               sigopts = sk_OPENSSL_STRING_new_null();
+                       if (!sigopts || !sk_OPENSSL_STRING_push(sigopts, *(++argv)))
+                               goto bad;
+                       }
                else if (strcmp(*argv,"-batch") == 0)
                        batch=1;
                else if (strcmp(*argv,"-newhdr") == 0)
@@ -858,8 +867,9 @@ loop:
                                        extensions);
                                goto end;
                                }
-                       
-                       if (!(i=X509_sign(x509ss,pkey,digest)))
+
+                       i=do_X509_sign(bio_err, x509ss, pkey, digest, sigopts);
+                       if (!i)
                                {
                                ERR_print_errors(bio_err);
                                goto end;
@@ -883,7 +893,8 @@ loop:
                                        req_exts);
                                goto end;
                                }
-                       if (!(i=X509_REQ_sign(req,pkey,digest)))
+                       i=do_X509_REQ_sign(bio_err, req, pkey, digest, sigopts);
+                       if (!i)
                                {
                                ERR_print_errors(bio_err);
                                goto end;
@@ -1084,6 +1095,8 @@ end:
                EVP_PKEY_CTX_free(genctx);
        if (pkeyopts)
                sk_OPENSSL_STRING_free(pkeyopts);
+       if (sigopts)
+               sk_OPENSSL_STRING_free(sigopts);
 #ifndef OPENSSL_NO_ENGINE
        if (gen_eng)
                ENGINE_free(gen_eng);
@@ -1756,3 +1769,68 @@ static int genpkey_cb(EVP_PKEY_CTX *ctx)
 #endif
        return 1;
        }
+
+static int do_sign_init(BIO *err, EVP_MD_CTX *ctx, EVP_PKEY *pkey,
+                       const EVP_MD *md, STACK_OF(OPENSSL_STRING) *sigopts)
+       {
+       EVP_PKEY_CTX *pkctx = NULL;
+       int i;
+       EVP_MD_CTX_init(ctx);
+       if (!EVP_DigestSignInit(ctx, &pkctx, md, NULL, pkey))
+               return 0;
+       for (i = 0; i < sk_OPENSSL_STRING_num(sigopts); i++)
+               {
+               char *sigopt = sk_OPENSSL_STRING_value(sigopts, i);
+               if (pkey_ctrl_string(pkctx, sigopt) <= 0)
+                       {
+                       BIO_printf(err, "parameter error \"%s\"\n", sigopt);
+                       ERR_print_errors(bio_err);
+                       return 0;
+                       }
+               }
+       return 1;
+       }
+
+int do_X509_sign(BIO *err, X509 *x, EVP_PKEY *pkey, const EVP_MD *md,
+                       STACK_OF(OPENSSL_STRING) *sigopts)
+       {
+       int rv;
+       EVP_MD_CTX mctx;
+       EVP_MD_CTX_init(&mctx);
+       rv = do_sign_init(err, &mctx, pkey, md, sigopts);
+       if (rv > 0)
+               rv = X509_sign_ctx(x, &mctx);
+       EVP_MD_CTX_cleanup(&mctx);
+       return rv > 0 ? 1 : 0;
+       }
+
+
+int do_X509_REQ_sign(BIO *err, X509_REQ *x, EVP_PKEY *pkey, const EVP_MD *md,
+                       STACK_OF(OPENSSL_STRING) *sigopts)
+       {
+       int rv;
+       EVP_MD_CTX mctx;
+       EVP_MD_CTX_init(&mctx);
+       rv = do_sign_init(err, &mctx, pkey, md, sigopts);
+       if (rv > 0)
+               rv = X509_REQ_sign_ctx(x, &mctx);
+       EVP_MD_CTX_cleanup(&mctx);
+       return rv > 0 ? 1 : 0;
+       }
+               
+       
+
+int do_X509_CRL_sign(BIO *err, X509_CRL *x, EVP_PKEY *pkey, const EVP_MD *md,
+                       STACK_OF(OPENSSL_STRING) *sigopts)
+       {
+       int rv;
+       EVP_MD_CTX mctx;
+       EVP_MD_CTX_init(&mctx);
+       rv = do_sign_init(err, &mctx, pkey, md, sigopts);
+       if (rv > 0)
+               rv = X509_CRL_sign_ctx(x, &mctx);
+       EVP_MD_CTX_cleanup(&mctx);
+       return rv > 0 ? 1 : 0;
+       }
+               
+       
index c4f5512..2cd7337 100644 (file)
@@ -357,6 +357,12 @@ void MS_CALLBACK msg_cb(int write_p, int version, int content_type, const void *
        case TLS1_VERSION:
                str_version = "TLS 1.0 ";
                break;
+       case TLS1_1_VERSION:
+               str_version = "TLS 1.1 ";
+               break;
+       case TLS1_2_VERSION:
+               str_version = "TLS 1.2 ";
+               break;
        case DTLS1_VERSION:
                str_version = "DTLS 1.0 ";
                break;
@@ -549,6 +555,9 @@ void MS_CALLBACK msg_cb(int write_p, int version, int content_type, const void *
                                case 114:
                                        str_details2 = " bad_certificate_hash_value";
                                        break;
+                               case 115:
+                                       str_details2 = " unknown_psk_identity";
+                                       break;
                                        }
                                }
                        }
@@ -597,6 +606,26 @@ void MS_CALLBACK msg_cb(int write_p, int version, int content_type, const void *
                                        }
                                }
                        }
+
+#ifndef OPENSSL_NO_HEARTBEATS
+               if (content_type == 24) /* Heartbeat */
+                       {
+                       str_details1 = ", Heartbeat";
+                       
+                       if (len > 0)
+                               {
+                               switch (((const unsigned char*)buf)[0])
+                                       {
+                               case 1:
+                                       str_details1 = ", HeartbeatRequest";
+                                       break;
+                               case 2:
+                                       str_details1 = ", HeartbeatResponse";
+                                       break;
+                                       }
+                               }
+                       }
+#endif
                }
 
        BIO_printf(bio, "%s %s%s [length %04lx]%s%s\n", str_write_p, str_version, str_content_type, (unsigned long)len, str_details1, str_details2);
@@ -657,6 +686,22 @@ void MS_CALLBACK tlsext_cb(SSL *s, int client_server, int type,
                extname = "status request";
                break;
 
+               case TLSEXT_TYPE_user_mapping:
+               extname = "user mapping";
+               break;
+
+               case TLSEXT_TYPE_client_authz:
+               extname = "client authz";
+               break;
+
+               case TLSEXT_TYPE_server_authz:
+               extname = "server authz";
+               break;
+
+               case TLSEXT_TYPE_cert_type:
+               extname = "cert type";
+               break;
+
                case TLSEXT_TYPE_elliptic_curves:
                extname = "elliptic curves";
                break;
@@ -665,12 +710,28 @@ void MS_CALLBACK tlsext_cb(SSL *s, int client_server, int type,
                extname = "EC point formats";
                break;
 
+               case TLSEXT_TYPE_srp:
+               extname = "SRP";
+               break;
+
+               case TLSEXT_TYPE_signature_algorithms:
+               extname = "signature algorithms";
+               break;
+
+               case TLSEXT_TYPE_use_srtp:
+               extname = "use SRTP";
+               break;
+
+               case TLSEXT_TYPE_heartbeat:
+               extname = "heartbeat";
+               break;
+
                case TLSEXT_TYPE_session_ticket:
-               extname = "server ticket";
+               extname = "session ticket";
                break;
 
-               case TLSEXT_TYPE_renegotiate:
-               extname = "renegotiate";
+               case TLSEXT_TYPE_renegotiate: 
+               extname = "renegotiation info";
                break;
 
 #ifdef TLSEXT_TYPE_opaque_prf_input
@@ -678,6 +739,11 @@ void MS_CALLBACK tlsext_cb(SSL *s, int client_server, int type,
                extname = "opaque PRF input";
                break;
 #endif
+#ifdef TLSEXT_TYPE_next_proto_neg
+               case TLSEXT_TYPE_next_proto_neg:
+               extname = "next protocol";
+               break;
+#endif
 
                default:
                extname = "unknown";
index 53be0f8..098cce2 100644 (file)
@@ -163,6 +163,9 @@ typedef unsigned int u_int;
 #include <openssl/rand.h>
 #include <openssl/ocsp.h>
 #include <openssl/bn.h>
+#ifndef OPENSSL_NO_SRP
+#include <openssl/srp.h>
+#endif
 #include "s_apps.h"
 #include "timeouts.h"
 
@@ -203,6 +206,9 @@ static int c_status_req=0;
 static int c_msg=0;
 static int c_showcerts=0;
 
+static char *keymatexportlabel=NULL;
+static int keymatexportlen=20;
+
 static void sc_usage(void);
 static void print_stuff(BIO *berr,SSL *con,int full);
 #ifndef OPENSSL_NO_TLSEXT
@@ -316,12 +322,21 @@ static void sc_usage(void)
        BIO_printf(bio_err," -jpake arg    - JPAKE secret to use\n");
 # endif
 #endif
+#ifndef OPENSSL_NO_SRP
+       BIO_printf(bio_err," -srpuser user     - SRP authentification for 'user'\n");
+       BIO_printf(bio_err," -srppass arg      - password for 'user'\n");
+       BIO_printf(bio_err," -srp_lateuser     - SRP username into second ClientHello message\n");
+       BIO_printf(bio_err," -srp_moregroups   - Tolerate other than the known g N values.\n");
+       BIO_printf(bio_err," -srp_strength int - minimal mength in bits for N (default %d).\n",SRP_MINIMAL_N);
+#endif
        BIO_printf(bio_err," -ssl2         - just use SSLv2\n");
        BIO_printf(bio_err," -ssl3         - just use SSLv3\n");
+       BIO_printf(bio_err," -tls1_2       - just use TLSv1.2\n");
+       BIO_printf(bio_err," -tls1_1       - just use TLSv1.1\n");
        BIO_printf(bio_err," -tls1         - just use TLSv1\n");
        BIO_printf(bio_err," -dtls1        - just use DTLSv1\n");    
        BIO_printf(bio_err," -mtu          - set the link layer MTU\n");
-       BIO_printf(bio_err," -no_tls1/-no_ssl3/-no_ssl2 - turn off that protocol\n");
+       BIO_printf(bio_err," -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");
@@ -342,8 +357,14 @@ static void sc_usage(void)
        BIO_printf(bio_err," -tlsextdebug      - hex dump of all TLS extensions received\n");
        BIO_printf(bio_err," -status           - request certificate status from server\n");
        BIO_printf(bio_err," -no_ticket        - disable use of RFC4507bis session tickets\n");
+# if !defined(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," -legacy_renegotiation - enable use of legacy renegotiation (dangerous)\n");
+       BIO_printf(bio_err," -use_srtp profiles - Offer SRTP key management with a colon-separated profile list\n");
+       BIO_printf(bio_err," -keymatexport label   - Export keying material using label\n");
+       BIO_printf(bio_err," -keymatexportlen len  - Export len bytes of keying material (default 20)\n");
        }
 
 #ifndef OPENSSL_NO_TLSEXT
@@ -366,6 +387,156 @@ static int MS_CALLBACK ssl_servername_cb(SSL *s, int *ad, void *arg)
        
        return SSL_TLSEXT_ERR_OK;
        }
+
+#ifndef OPENSSL_NO_SRP
+
+/* This is a context that we pass to all callbacks */
+typedef struct srp_arg_st
+       {
+       char *srppassin;
+       char *srplogin;
+       int msg;   /* copy from c_msg */
+       int debug; /* copy from c_debug */
+       int amp;   /* allow more groups */
+       int strength /* minimal size for N */ ;
+       } SRP_ARG;
+
+#define SRP_NUMBER_ITERATIONS_FOR_PRIME 64
+
+static int srp_Verify_N_and_g(BIGNUM *N, BIGNUM *g)
+       {
+       BN_CTX *bn_ctx = BN_CTX_new();
+       BIGNUM *p = BN_new();
+       BIGNUM *r = BN_new();
+       int ret =
+               g != NULL && N != NULL && bn_ctx != NULL && BN_is_odd(N) &&
+               BN_is_prime_ex(N, SRP_NUMBER_ITERATIONS_FOR_PRIME, bn_ctx, NULL) &&
+               p != NULL && BN_rshift1(p, N) &&
+
+               /* p = (N-1)/2 */
+               BN_is_prime_ex(p, SRP_NUMBER_ITERATIONS_FOR_PRIME, bn_ctx, NULL) &&
+               r != NULL &&
+
+               /* verify g^((N-1)/2) == -1 (mod N) */
+               BN_mod_exp(r, g, p, N, bn_ctx) &&
+               BN_add_word(r, 1) &&
+               BN_cmp(r, N) == 0;
+
+       if(r)
+               BN_free(r);
+       if(p)
+               BN_free(p);
+       if(bn_ctx)
+               BN_CTX_free(bn_ctx);
+       return ret;
+       }
+
+/* This callback is used here for two purposes:
+   - extended debugging
+   - making some primality tests for unknown groups
+   The callback is only called for a non default group.
+
+   An application does not need the call back at all if
+   only the stanard groups are used.  In real life situations, 
+   client and server already share well known groups, 
+   thus there is no need to verify them. 
+   Furthermore, in case that a server actually proposes a group that
+   is not one of those defined in RFC 5054, it is more appropriate 
+   to add the group to a static list and then compare since 
+   primality tests are rather cpu consuming.
+*/
+
+static int MS_CALLBACK ssl_srp_verify_param_cb(SSL *s, void *arg)
+       {
+       SRP_ARG *srp_arg = (SRP_ARG *)arg;
+       BIGNUM *N = NULL, *g = NULL;
+       if (!(N = SSL_get_srp_N(s)) || !(g = SSL_get_srp_g(s)))
+               return 0;
+       if (srp_arg->debug || srp_arg->msg || srp_arg->amp == 1)
+               {
+               BIO_printf(bio_err, "SRP parameters:\n"); 
+               BIO_printf(bio_err,"\tN="); BN_print(bio_err,N);
+               BIO_printf(bio_err,"\n\tg="); BN_print(bio_err,g);
+               BIO_printf(bio_err,"\n");
+               }
+
+       if (SRP_check_known_gN_param(g,N))
+               return 1;
+
+       if (srp_arg->amp == 1)
+               {
+               if (srp_arg->debug)
+                       BIO_printf(bio_err, "SRP param N and g are not known params, going to check deeper.\n");
+
+/* The srp_moregroups is a real debugging feature.
+   Implementors should rather add the value to the known ones.
+   The minimal size has already been tested.
+*/
+               if (BN_num_bits(g) <= BN_BITS && srp_Verify_N_and_g(N,g))
+                       return 1;
+               }       
+       BIO_printf(bio_err, "SRP param N and g rejected.\n");
+       return 0;
+       }
+
+#define PWD_STRLEN 1024
+
+static char * MS_CALLBACK ssl_give_srp_client_pwd_cb(SSL *s, void *arg)
+       {
+       SRP_ARG *srp_arg = (SRP_ARG *)arg;
+       char *pass = (char *)OPENSSL_malloc(PWD_STRLEN+1);
+       PW_CB_DATA cb_tmp;
+       int l;
+
+       cb_tmp.password = (char *)srp_arg->srppassin;
+       cb_tmp.prompt_info = "SRP user";
+       if ((l = password_callback(pass, PWD_STRLEN, 0, &cb_tmp))<0)
+               {
+               BIO_printf (bio_err, "Can't read Password\n");
+               OPENSSL_free(pass);
+               return NULL;
+               }
+       *(pass+l)= '\0';
+
+       return pass;
+       }
+
+#endif
+       char *srtp_profiles = NULL;
+
+# ifndef OPENSSL_NO_NEXTPROTONEG
+/* This the context that we pass to next_proto_cb */
+typedef struct tlsextnextprotoctx_st {
+       unsigned char *data;
+       unsigned short len;
+       int status;
+} tlsextnextprotoctx;
+
+static tlsextnextprotoctx next_proto;
+
+static int next_proto_cb(SSL *s, unsigned char **out, unsigned char *outlen, const unsigned char *in, unsigned int inlen, void *arg)
+       {
+       tlsextnextprotoctx *ctx = arg;
+
+       if (!c_quiet)
+               {
+               /* We can assume that |in| is syntactically valid. */
+               unsigned i;
+               BIO_printf(bio_c_out, "Protocols advertised by server: ");
+               for (i = 0; i < inlen; )
+                       {
+                       if (i)
+                               BIO_write(bio_c_out, ", ", 2);
+                       BIO_write(bio_c_out, &in[i + 1], in[i]);
+                       i += in[i] + 1;
+                       }
+               BIO_write(bio_c_out, "\n", 1);
+               }
+
+       ctx->status = SSL_select_next_proto(out, outlen, in, inlen, ctx->data, ctx->len);
+       return SSL_TLSEXT_ERR_OK;
+       }
+# endif
 #endif
 
 enum
@@ -384,6 +555,9 @@ int MAIN(int argc, char **argv)
        {
        unsigned int off=0, clr=0;
        SSL *con=NULL;
+#ifndef OPENSSL_NO_KRB5
+       KSSL_CTX *kctx;
+#endif
        int s,k,width,state=0;
        char *cbuf=NULL,*sbuf=NULL,*mbuf=NULL;
        int cbuf_len,cbuf_off;
@@ -429,6 +603,9 @@ int MAIN(int argc, char **argv)
        char *servername = NULL; 
         tlsextctx tlsextcbp = 
         {NULL,0};
+# ifndef OPENSSL_NO_NEXTPROTONEG
+       const char *next_proto_neg_in = NULL;
+# endif
 #endif
        char *sess_in = NULL;
        char *sess_out = NULL;
@@ -439,6 +616,11 @@ int MAIN(int argc, char **argv)
 #ifndef OPENSSL_NO_JPAKE
        char *jpake_secret = NULL;
 #endif
+#ifndef OPENSSL_NO_SRP
+       char * srppass = NULL;
+       int srp_lateuser = 0;
+       SRP_ARG srp_arg = {NULL,NULL,0,0,0,1024};
+#endif
 
 #if !defined(OPENSSL_NO_SSL2) && !defined(OPENSSL_NO_SSL3)
        meth=SSLv23_client_method();
@@ -588,6 +770,37 @@ int MAIN(int argc, char **argv)
                                 }
                        }
 #endif
+#ifndef OPENSSL_NO_SRP
+               else if (strcmp(*argv,"-srpuser") == 0)
+                       {
+                       if (--argc < 1) goto bad;
+                       srp_arg.srplogin= *(++argv);
+                       meth=TLSv1_client_method();
+                       }
+               else if (strcmp(*argv,"-srppass") == 0)
+                       {
+                       if (--argc < 1) goto bad;
+                       srppass= *(++argv);
+                       meth=TLSv1_client_method();
+                       }
+               else if (strcmp(*argv,"-srp_strength") == 0)
+                       {
+                       if (--argc < 1) goto bad;
+                       srp_arg.strength=atoi(*(++argv));
+                       BIO_printf(bio_err,"SRP minimal length for N is %d\n",srp_arg.strength);
+                       meth=TLSv1_client_method();
+                       }
+               else if (strcmp(*argv,"-srp_lateuser") == 0)
+                       {
+                       srp_lateuser= 1;
+                       meth=TLSv1_client_method();
+                       }
+               else if (strcmp(*argv,"-srp_moregroups") == 0)
+                       {
+                       srp_arg.amp=1;
+                       meth=TLSv1_client_method();
+                       }
+#endif
 #ifndef OPENSSL_NO_SSL2
                else if (strcmp(*argv,"-ssl2") == 0)
                        meth=SSLv2_client_method();
@@ -597,6 +810,10 @@ int MAIN(int argc, char **argv)
                        meth=SSLv3_client_method();
 #endif
 #ifndef OPENSSL_NO_TLS1
+               else if (strcmp(*argv,"-tls1_2") == 0)
+                       meth=TLSv1_2_client_method();
+               else if (strcmp(*argv,"-tls1_1") == 0)
+                       meth=TLSv1_1_client_method();
                else if (strcmp(*argv,"-tls1") == 0)
                        meth=TLSv1_client_method();
 #endif
@@ -645,6 +862,10 @@ int MAIN(int argc, char **argv)
                        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)
@@ -656,6 +877,13 @@ int MAIN(int argc, char **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) goto bad;
+                       next_proto_neg_in = *(++argv);
+                       }
+# endif
 #endif
                else if (strcmp(*argv,"-serverpref") == 0)
                        off|=SSL_OP_CIPHER_SERVER_PREFERENCE;
@@ -723,7 +951,23 @@ int MAIN(int argc, char **argv)
                        jpake_secret = *++argv;
                        }
 #endif
-               else
+               else if (strcmp(*argv,"-use_srtp") == 0)
+                       {
+                       if (--argc < 1) goto bad;
+                       srtp_profiles = *(++argv);
+                       }
+               else if (strcmp(*argv,"-keymatexport") == 0)
+                       {
+                       if (--argc < 1) goto bad;
+                       keymatexportlabel= *(++argv);
+                       }
+               else if (strcmp(*argv,"-keymatexportlen") == 0)
+                       {
+                       if (--argc < 1) goto bad;
+                       keymatexportlen=atoi(*(++argv));
+                       if (keymatexportlen == 0) goto bad;
+                       }
+                else
                        {
                        BIO_printf(bio_err,"unknown option %s\n",*argv);
                        badop=1;
@@ -749,19 +993,33 @@ bad:
                        goto end;
                        }
                psk_identity = "JPAKE";
+               if (cipher)
+                       {
+                       BIO_printf(bio_err, "JPAKE sets cipher to PSK\n");
+                       goto end;
+                       }
+               cipher = "PSK";
                }
-
-       if (cipher)
-               {
-               BIO_printf(bio_err, "JPAKE sets cipher to PSK\n");
-               goto end;
-               }
-       cipher = "PSK";
 #endif
 
        OpenSSL_add_ssl_algorithms();
        SSL_load_error_strings();
 
+#if !defined(OPENSSL_NO_TLSEXT) && !defined(OPENSSL_NO_NEXTPROTONEG)
+       next_proto.status = -1;
+       if (next_proto_neg_in)
+               {
+               next_proto.data = next_protos_parse(&next_proto.len, next_proto_neg_in);
+               if (next_proto.data == NULL)
+                       {
+                       BIO_printf(bio_err, "Error parsing -nextprotoneg argument\n");
+                       goto end;
+                       }
+               }
+       else
+               next_proto.data = NULL;
+#endif
+
 #ifndef OPENSSL_NO_ENGINE
         e = setup_engine(bio_err, engine_id, 1);
        if (ssl_client_engine_id)
@@ -835,6 +1093,14 @@ bad:
                        }
                }
 
+#ifndef OPENSSL_NO_SRP
+       if(!app_passwd(bio_err, srppass, NULL, &srp_arg.srppassin, NULL))
+               {
+               BIO_printf(bio_err, "Error getting password\n");
+               goto end;
+               }
+#endif
+
        ctx=SSL_CTX_new(meth);
        if (ctx == NULL)
                {
@@ -870,6 +1136,8 @@ bad:
                        BIO_printf(bio_c_out, "PSK key given or JPAKE in use, setting client callback\n");
                SSL_CTX_set_psk_client_callback(ctx, psk_client_cb);
                }
+       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);
@@ -883,6 +1151,11 @@ bad:
         */
        if (socket_type == SOCK_DGRAM) SSL_CTX_set_read_ahead(ctx, 1);
 
+#if !defined(OPENSSL_NO_TLSEXT) && !defined(OPENSSL_NO_NEXTPROTONEG)
+       if (next_proto.data)
+               SSL_CTX_set_next_proto_select_cb(ctx, next_proto_cb, &next_proto);
+#endif
+
        if (state) SSL_CTX_set_info_callback(ctx,apps_ssl_info_callback);
        if (cipher != NULL)
                if(!SSL_CTX_set_cipher_list(ctx,cipher)) {
@@ -914,6 +1187,24 @@ bad:
                SSL_CTX_set_tlsext_servername_callback(ctx, ssl_servername_cb);
                SSL_CTX_set_tlsext_servername_arg(ctx, &tlsextcbp);
                }
+#ifndef OPENSSL_NO_SRP
+        if (srp_arg.srplogin)
+               {
+               if (!srp_lateuser && !SSL_CTX_set_srp_username(ctx, srp_arg.srplogin))
+                       {
+                       BIO_printf(bio_err,"Unable to set SRP username\n");
+                       goto end;
+                       }
+               srp_arg.msg = c_msg;
+               srp_arg.debug = c_debug ;
+               SSL_CTX_set_srp_cb_arg(ctx,&srp_arg);
+               SSL_CTX_set_srp_client_pwd_callback(ctx, ssl_give_srp_client_pwd_cb);
+               SSL_CTX_set_srp_strength(ctx, srp_arg.strength);
+               if (c_msg || c_debug || srp_arg.amp == 0)
+                       SSL_CTX_set_srp_verify_param_callback(ctx, ssl_srp_verify_param_cb);
+               }
+
+#endif
 #endif
 
        con=SSL_new(ctx);
@@ -952,9 +1243,10 @@ bad:
                }
 #endif
 #ifndef OPENSSL_NO_KRB5
-       if (con  &&  (con->kssl_ctx = kssl_ctx_new()) != NULL)
+       if (con  &&  (kctx = kssl_ctx_new()) != NULL)
                 {
-                kssl_ctx_setstring(con->kssl_ctx, KSSL_SERVER, host);
+               SSL_set0_kssl_ctx(con, kctx);
+                kssl_ctx_setstring(kctx, KSSL_SERVER, host);
                }
 #endif /* OPENSSL_NO_KRB5  */
 /*     SSL_set_cipher_list(con,"RC4-MD5"); */
@@ -986,7 +1278,7 @@ re_start:
                        }
                }
 #endif                                              
-       if (c_Pause & 0x01) con->debug=1;
+       if (c_Pause & 0x01) SSL_set_debug(con, 1);
 
        if ( SSL_version(con) == DTLS1_VERSION)
                {
@@ -1035,7 +1327,7 @@ re_start:
 
        if (c_debug)
                {
-               con->debug=1;
+               SSL_set_debug(con, 1);
                BIO_set_callback(sbio,bio_dump_callback);
                BIO_set_callback_arg(sbio,(char *)bio_c_out);
                }
@@ -1569,6 +1861,14 @@ printf("read=%d pending=%d peek=%d\n",k,SSL_pending(con),SSL_peek(con,zbuf,10240
                                SSL_renegotiate(con);
                                cbuf_len=0;
                                }
+#ifndef OPENSSL_NO_HEARTBEATS
+                       else if ((!c_ign_eof) && (cbuf[0] == 'B'))
+                               {
+                               BIO_printf(bio_err,"HEARTBEATING\n");
+                               SSL_heartbeat(con);
+                               cbuf_len=0;
+                               }
+#endif
                        else
                                {
                                cbuf_len=i;
@@ -1630,6 +1930,7 @@ static void print_stuff(BIO *bio, SSL *s, int full)
 #ifndef OPENSSL_NO_COMP
        const COMP_METHOD *comp, *expansion;
 #endif
+       unsigned char *exportedkeymat;
 
        if (full)
                {
@@ -1720,7 +2021,7 @@ static void print_stuff(BIO *bio, SSL *s, int full)
                        BIO_number_read(SSL_get_rbio(s)),
                        BIO_number_written(SSL_get_wbio(s)));
                }
-       BIO_printf(bio,((s->hit)?"---\nReused, ":"---\nNew, "));
+       BIO_printf(bio,(SSL_cache_hit(s)?"---\nReused, ":"---\nNew, "));
        c=SSL_get_current_cipher(s);
        BIO_printf(bio,"%s, Cipher is %s\n",
                SSL_CIPHER_get_version(c),
@@ -1742,7 +2043,66 @@ static void print_stuff(BIO *bio, SSL *s, int full)
        BIO_printf(bio,"Expansion: %s\n",
                expansion ? SSL_COMP_get_name(expansion) : "NONE");
 #endif
+#ifdef SSL_DEBUG
+       {
+       /* Print out local port of connection: useful for debugging */
+       int sock;
+       struct sockaddr_in ladd;
+       socklen_t ladd_size = sizeof(ladd);
+       sock = SSL_get_fd(s);
+       getsockname(sock, (struct sockaddr *)&ladd, &ladd_size);
+       BIO_printf(bio_c_out, "LOCAL PORT is %u\n", ntohs(ladd.sin_port));
+       }
+#endif
+
+#if !defined(OPENSSL_NO_TLSEXT) && !defined(OPENSSL_NO_NEXTPROTONEG)
+       if (next_proto.status != -1) {
+               const unsigned char *proto;
+               unsigned int proto_len;
+               SSL_get0_next_proto_negotiated(s, &proto, &proto_len);
+               BIO_printf(bio, "Next protocol: (%d) ", next_proto.status);
+               BIO_write(bio, proto, proto_len);
+               BIO_write(bio, "\n", 1);
+       }
+#endif
+
+       {
+       SRTP_PROTECTION_PROFILE *srtp_profile=SSL_get_selected_srtp_profile(s);
+       if(srtp_profile)
+               BIO_printf(bio,"SRTP Extension negotiated, profile=%s\n",
+                          srtp_profile->name);
+       }
        SSL_SESSION_print(bio,SSL_get_session(s));
+       if (keymatexportlabel != NULL)
+               {
+               BIO_printf(bio, "Keying material exporter:\n");
+               BIO_printf(bio, "    Label: '%s'\n", keymatexportlabel);
+               BIO_printf(bio, "    Length: %i bytes\n", keymatexportlen);
+               exportedkeymat = OPENSSL_malloc(keymatexportlen);
+               if (exportedkeymat != NULL)
+                       {
+                       if (!SSL_export_keying_material(s, exportedkeymat,
+                                                       keymatexportlen,
+                                                       keymatexportlabel,
+                                                       strlen(keymatexportlabel),
+                                                       NULL, 0, 0))
+                               {
+                               BIO_printf(bio, "    Error\n");
+                               }
+                       else
+                               {
+                               BIO_printf(bio, "    Keying material: ");
+                               for (i=0; i<keymatexportlen; i++)
+                                       BIO_printf(bio, "%02X",
+                                                  exportedkeymat[i]);
+                               BIO_printf(bio, "\n");
+                               }
+                       OPENSSL_free(exportedkeymat);
+                       }
+               }
        BIO_printf(bio,"---\n");
        if (peer != NULL)
                X509_free(peer);
index a3a04d4..fe29b4c 100644 (file)
@@ -186,6 +186,9 @@ typedef unsigned int u_int;
 #ifndef OPENSSL_NO_RSA
 #include <openssl/rsa.h>
 #endif
+#ifndef OPENSSL_NO_SRP
+#include <openssl/srp.h>
+#endif
 #include "s_apps.h"
 #include "timeouts.h"
 
@@ -290,6 +293,9 @@ static int cert_status_cb(SSL *s, void *arg);
 static int s_msg=0;
 static int s_quiet=0;
 
+static char *keymatexportlabel=NULL;
+static int keymatexportlen=20;
+
 static int hack=0;
 #ifndef OPENSSL_NO_ENGINE
 static char *engine_id=NULL;
@@ -302,6 +308,7 @@ static long socket_mtu;
 static int cert_chain = 0;
 #endif
 
+
 #ifndef OPENSSL_NO_PSK
 static char *psk_identity="Client_identity";
 char *psk_key=NULL; /* by default PSK is not used */
@@ -369,6 +376,52 @@ static unsigned int psk_server_cb(SSL *ssl, const char *identity,
         }
 #endif
 
+#ifndef OPENSSL_NO_SRP
+/* This is a context that we pass to callbacks */
+typedef struct srpsrvparm_st
+       {
+       char *login;
+       SRP_VBASE *vb;
+       SRP_user_pwd *user;
+       } srpsrvparm;
+
+/* This callback pretends to require some asynchronous logic in order to obtain
+   a verifier. When the callback is called for a new connection we return
+   with a negative value. This will provoke the accept etc to return with
+   an LOOKUP_X509. The main logic of the reinvokes the suspended call 
+   (which would normally occur after a worker has finished) and we
+   set the user parameters. 
+*/
+static int MS_CALLBACK ssl_srp_server_param_cb(SSL *s, int *ad, void *arg)
+       {
+       srpsrvparm *p = (srpsrvparm *)arg;
+       if (p->login == NULL && p->user == NULL )
+               {
+               p->login = SSL_get_srp_username(s);
+               BIO_printf(bio_err, "SRP username = \"%s\"\n", p->login);
+               return (-1) ;
+               }
+
+       if (p->user == NULL)
+               {
+               BIO_printf(bio_err, "User %s doesn't exist\n", p->login);
+               return SSL3_AL_FATAL;
+               }
+       if (SSL_set_srp_server_param(s, p->user->N, p->user->g, p->user->s, p->user->v,
+                                    p->user->info) < 0)
+               {
+               *ad = SSL_AD_INTERNAL_ERROR;
+               return SSL3_AL_FATAL;
+               }
+       BIO_printf(bio_err, "SRP parameters set: username = \"%s\" info=\"%s\" \n", p->login,p->user->info);
+       /* need to check whether there are memory leaks */
+       p->user = NULL;
+       p->login = NULL;
+       return SSL_ERROR_NONE;
+       }
+
+#endif
+
 #ifdef MONOLITH
 static void s_server_init(void)
        {
@@ -456,8 +509,14 @@ static void sv_usage(void)
        BIO_printf(bio_err," -jpake arg    - JPAKE secret to use\n");
 # endif
 #endif
+#ifndef OPENSSL_NO_SRP
+       BIO_printf(bio_err," -srpvfile file      - The verifier file for SRP\n");
+       BIO_printf(bio_err," -srpuserseed string - A seed string for a default user salt.\n");
+#endif
        BIO_printf(bio_err," -ssl2         - Just talk SSLv2\n");
        BIO_printf(bio_err," -ssl3         - Just talk SSLv3\n");
+       BIO_printf(bio_err," -tls1_2       - Just talk TLSv1.2\n");
+       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," -timeout      - Enable timeouts\n");
@@ -466,6 +525,8 @@ static void sv_usage(void)
        BIO_printf(bio_err," -no_ssl2      - Just disable SSLv2\n");
        BIO_printf(bio_err," -no_ssl3      - Just disable SSLv3\n");
        BIO_printf(bio_err," -no_tls1      - Just disable TLSv1\n");
+       BIO_printf(bio_err," -no_tls1_1    - Just disable TLSv1.1\n");
+       BIO_printf(bio_err," -no_tls1_2    - Just disable TLSv1.2\n");
 #ifndef OPENSSL_NO_DH
        BIO_printf(bio_err," -no_dhe       - Disable ephemeral DH\n");
 #endif
@@ -492,7 +553,13 @@ static void sv_usage(void)
        BIO_printf(bio_err," -tlsextdebug  - hex dump of all TLS extensions received\n");
        BIO_printf(bio_err," -no_ticket    - disable use of RFC4507bis session tickets\n");
        BIO_printf(bio_err," -legacy_renegotiation - enable use of legacy renegotiation (dangerous)\n");
+# ifndef OPENSSL_NO_NEXTPROTONEG
+       BIO_printf(bio_err," -nextprotoneg arg - set the advertised protocols for the NPN extension (comma-separated list)\n");
+# endif
+        BIO_printf(bio_err," -use_srtp profiles - Offer SRTP key management with a colon-separated profile list\n");
 #endif
+       BIO_printf(bio_err," -keymatexport label   - Export keying material using label\n");
+       BIO_printf(bio_err," -keymatexportlen len  - Export len bytes of keying material (default 20)\n");
        }
 
 static int local_argc=0;
@@ -826,6 +893,26 @@ BIO_printf(err, "cert_status: received %d ids\n", sk_OCSP_RESPID_num(ids));
        ret = SSL_TLSEXT_ERR_ALERT_FATAL;
        goto done;
        }
+
+# ifndef OPENSSL_NO_NEXTPROTONEG
+/* This is the context that we pass to next_proto_cb */
+typedef struct tlsextnextprotoctx_st {
+       unsigned char *data;
+       unsigned int len;
+} tlsextnextprotoctx;
+
+static int next_proto_cb(SSL *s, const unsigned char **data, unsigned int *len, void *arg)
+       {
+       tlsextnextprotoctx *next_proto = arg;
+
+       *data = next_proto->data;
+       *len = next_proto->len;
+
+       return SSL_TLSEXT_ERR_OK;
+       }
+# endif  /* ndef OPENSSL_NO_NEXTPROTONEG */
+
+
 #endif
 
 int MAIN(int, char **);
@@ -833,6 +920,10 @@ int MAIN(int, char **);
 #ifndef OPENSSL_NO_JPAKE
 static char *jpake_secret = NULL;
 #endif
+#ifndef OPENSSL_NO_SRP
+       static srpsrvparm srp_callback_parm;
+#endif
+static char *srtp_profiles = NULL;
 
 int MAIN(int argc, char *argv[])
        {
@@ -864,20 +955,30 @@ int MAIN(int argc, char *argv[])
 #ifndef OPENSSL_NO_TLSEXT
        EVP_PKEY *s_key2 = NULL;
        X509 *s_cert2 = NULL;
-#endif
-#ifndef OPENSSL_NO_TLSEXT
         tlsextctx tlsextcbp = {NULL, NULL, SSL_TLSEXT_ERR_ALERT_WARNING};
+# ifndef OPENSSL_NO_NEXTPROTONEG
+       const char *next_proto_neg_in = NULL;
+       tlsextnextprotoctx next_proto;
+# endif
 #endif
 #ifndef OPENSSL_NO_PSK
        /* by default do not send a PSK identity hint */
        static char *psk_identity_hint=NULL;
 #endif
+#ifndef OPENSSL_NO_SRP
+       char *srpuserseed = NULL;
+       char *srp_verifier_file = NULL;
+#endif
 #if !defined(OPENSSL_NO_SSL2) && !defined(OPENSSL_NO_SSL3)
        meth=SSLv23_server_method();
 #elif !defined(OPENSSL_NO_SSL3)
        meth=SSLv3_server_method();
 #elif !defined(OPENSSL_NO_SSL2)
        meth=SSLv2_server_method();
+#elif !defined(OPENSSL_NO_TLS1)
+       meth=TLSv1_server_method();
+#else
+  /*  #error no SSL version enabled */
 #endif
 
        local_argc=argc;
@@ -1110,6 +1211,20 @@ int MAIN(int argc, char *argv[])
                                }
                        }
 #endif
+#ifndef OPENSSL_NO_SRP
+               else if (strcmp(*argv, "-srpvfile") == 0)
+                       {
+                       if (--argc < 1) goto bad;
+                       srp_verifier_file = *(++argv);
+                       meth=TLSv1_server_method();
+                       }
+               else if (strcmp(*argv, "-srpuserseed") == 0)
+                       {
+                       if (--argc < 1) goto bad;
+                       srpuserseed = *(++argv);
+                       meth=TLSv1_server_method();
+                       }
+#endif
                else if (strcmp(*argv,"-www") == 0)
                        { www=1; }
                else if (strcmp(*argv,"-WWW") == 0)
@@ -1122,6 +1237,10 @@ int MAIN(int argc, char *argv[])
                        { 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
@@ -1139,6 +1258,10 @@ int MAIN(int argc, char *argv[])
 #ifndef OPENSSL_NO_TLS1
                else if (strcmp(*argv,"-tls1") == 0)
                        { meth=TLSv1_server_method(); }
+               else if (strcmp(*argv,"-tls1_1") == 0)
+                       { meth=TLSv1_1_server_method(); }
+               else if (strcmp(*argv,"-tls1_2") == 0)
+                       { meth=TLSv1_2_server_method(); }
 #endif
 #ifndef OPENSSL_NO_DTLS1
                else if (strcmp(*argv,"-dtls1") == 0)
@@ -1191,7 +1314,13 @@ int MAIN(int argc, char *argv[])
                        if (--argc < 1) goto bad;
                        s_key_file2= *(++argv);
                        }
-                       
+# ifndef OPENSSL_NO_NEXTPROTONEG
+               else if (strcmp(*argv,"-nextprotoneg") == 0)
+                       {
+                       if (--argc < 1) goto bad;
+                       next_proto_neg_in = *(++argv);
+                       }
+# endif
 #endif
 #if !defined(OPENSSL_NO_JPAKE) && !defined(OPENSSL_NO_PSK)
                else if (strcmp(*argv,"-jpake") == 0)
@@ -1200,6 +1329,22 @@ int MAIN(int argc, char *argv[])
                        jpake_secret = *(++argv);
                        }
 #endif
+               else if (strcmp(*argv,"-use_srtp") == 0)
+                       {
+                       if (--argc < 1) goto bad;
+                       srtp_profiles = *(++argv);
+                       }
+               else if (strcmp(*argv,"-keymatexport") == 0)
+                       {
+                       if (--argc < 1) goto bad;
+                       keymatexportlabel= *(++argv);
+                       }
+               else if (strcmp(*argv,"-keymatexportlen") == 0)
+                       {
+                       if (--argc < 1) goto bad;
+                       keymatexportlen=atoi(*(++argv));
+                       if (keymatexportlen == 0) goto bad;
+                       }
                else
                        {
                        BIO_printf(bio_err,"unknown option %s\n",*argv);
@@ -1296,6 +1441,22 @@ bad:
                                goto end;
                                }
                        }
+
+# ifndef OPENSSL_NO_NEXTPROTONEG
+               if (next_proto_neg_in)
+                       {
+                       unsigned short len;
+                       next_proto.data = next_protos_parse(&len,
+                               next_proto_neg_in);
+                       if (next_proto.data == NULL)
+                               goto end;
+                       next_proto.len = len;
+                       }
+               else
+                       {
+                       next_proto.data = NULL;
+                       }
+# endif
 #endif
                }
 
@@ -1399,6 +1560,9 @@ bad:
        else
                SSL_CTX_sess_set_cache_size(ctx,128);
 
+       if (srtp_profiles != NULL)
+               SSL_CTX_set_tlsext_use_srtp(ctx, srtp_profiles);
+
 #if 0
        if (cipher == NULL) cipher=getenv("SSL_CIPHER");
 #endif
@@ -1476,6 +1640,11 @@ bad:
                if (vpm)
                        SSL_CTX_set1_param(ctx2, vpm);
                }
+
+# ifndef OPENSSL_NO_NEXTPROTONEG
+       if (next_proto.data)
+               SSL_CTX_set_next_protos_advertised_cb(ctx, next_proto_cb, &next_proto);
+# endif
 #endif 
 
 #ifndef OPENSSL_NO_DH
@@ -1684,6 +1853,25 @@ bad:
                }
 #endif
 
+#ifndef OPENSSL_NO_SRP
+       if (srp_verifier_file != NULL)
+               {
+               srp_callback_parm.vb = SRP_VBASE_new(srpuserseed);
+               srp_callback_parm.user = NULL;
+               srp_callback_parm.login = NULL;
+               if ((ret = SRP_VBASE_init(srp_callback_parm.vb, srp_verifier_file)) != SRP_NO_ERROR)
+                       {
+                       BIO_printf(bio_err,
+                                  "Cannot initialize SRP verifier file \"%s\":ret=%d\n",
+                                  srp_verifier_file, ret);
+                               goto end;
+                       }
+               SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE,verify_callback);
+               SSL_CTX_set_srp_cb_arg(ctx, &srp_callback_parm);                        
+               SSL_CTX_set_srp_username_callback(ctx, ssl_srp_server_param_cb);
+               }
+       else
+#endif
        if (CAfile != NULL)
                {
                SSL_CTX_set_client_CA_list(ctx,SSL_load_client_CA_file(CAfile));
@@ -1765,6 +1953,9 @@ static int sv_body(char *hostname, int s, unsigned char *context)
        unsigned long l;
        SSL *con=NULL;
        BIO *sbio;
+#ifndef OPENSSL_NO_KRB5
+       KSSL_CTX *kctx;
+#endif
        struct timeval timeout;
 #if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_MSDOS) || defined(OPENSSL_SYS_NETWARE) || defined(OPENSSL_SYS_BEOS_R5)
        struct timeval tv;
@@ -1805,12 +1996,11 @@ static int sv_body(char *hostname, int s, unsigned char *context)
                }
 #endif
 #ifndef OPENSSL_NO_KRB5
-               if ((con->kssl_ctx = kssl_ctx_new()) != NULL)
+               if ((kctx = kssl_ctx_new()) != NULL)
                         {
-                        kssl_ctx_setstring(con->kssl_ctx, KSSL_SERVICE,
-                                                               KRB5SVC);
-                        kssl_ctx_setstring(con->kssl_ctx, KSSL_KEYTAB,
-                                                               KRB5KEYTAB);
+                       SSL_set0_kssl_ctx(con, kctx);
+                        kssl_ctx_setstring(kctx, KSSL_SERVICE, KRB5SVC);
+                        kssl_ctx_setstring(kctx, KSSL_KEYTAB, KRB5KEYTAB);
                         }
 #endif /* OPENSSL_NO_KRB5 */
                if(context)
@@ -1873,7 +2063,7 @@ static int sv_body(char *hostname, int s, unsigned char *context)
 
        if (s_debug)
                {
-               con->debug=1;
+               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);
                }
@@ -2002,6 +2192,16 @@ static int sv_body(char *hostname, int s, unsigned char *context)
                                        goto err;
                                        }
 
+#ifndef OPENSSL_NO_HEARTBEATS
+                               if ((buf[0] == 'B') &&
+                                       ((buf[1] == '\n') || (buf[1] == '\r')))
+                                       {
+                                       BIO_printf(bio_err,"HEARTBEATING\n");
+                                       SSL_heartbeat(con);
+                                       i=0;
+                                       continue;
+                                       }
+#endif
                                if ((buf[0] == 'r') && 
                                        ((buf[1] == '\n') || (buf[1] == '\r')))
                                        {
@@ -2045,6 +2245,18 @@ static int sv_body(char *hostname, int s, unsigned char *context)
 { static count=0; if (++count == 100) { count=0; SSL_renegotiate(con); } }
 #endif
                                k=SSL_write(con,&(buf[l]),(unsigned int)i);
+#ifndef OPENSSL_NO_SRP
+                               while (SSL_get_error(con,k) == SSL_ERROR_WANT_X509_LOOKUP)
+                                       {
+                                       BIO_printf(bio_s_out,"LOOKUP renego during write\n");
+                                       srp_callback_parm.user = SRP_VBASE_get_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");
+                                               k=SSL_write(con,&(buf[l]),(unsigned int)i);
+                                       }
+#endif
                                switch (SSL_get_error(con,k))
                                        {
                                case SSL_ERROR_NONE:
@@ -2092,6 +2304,18 @@ static int sv_body(char *hostname, int s, unsigned char *context)
                                {
 again: 
                                i=SSL_read(con,(char *)buf,bufsize);
+#ifndef OPENSSL_NO_SRP
+                               while (SSL_get_error(con,i) == SSL_ERROR_WANT_X509_LOOKUP)
+                                       {
+                                       BIO_printf(bio_s_out,"LOOKUP renego during read\n");
+                                       srp_callback_parm.user = SRP_VBASE_get_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");
+                                       i=SSL_read(con,(char *)buf,bufsize);
+                                       }
+#endif
                                switch (SSL_get_error(con,i))
                                        {
                                case SSL_ERROR_NONE:
@@ -2104,7 +2328,6 @@ again:
                                        break;
                                case SSL_ERROR_WANT_WRITE:
                                case SSL_ERROR_WANT_READ:
-                               case SSL_ERROR_WANT_X509_LOOKUP:
                                        BIO_printf(bio_s_out,"Read BLOCK\n");
                                        break;
                                case SSL_ERROR_SYSCALL:
@@ -2159,8 +2382,30 @@ static int init_ssl_connection(SSL *con)
        X509 *peer;
        long verify_error;
        MS_STATIC char buf[BUFSIZ];
+#ifndef OPENSSL_NO_KRB5
+       char *client_princ;
+#endif
+#if !defined(OPENSSL_NO_TLSEXT) && !defined(OPENSSL_NO_NEXTPROTONEG)
+       const unsigned char *next_proto_neg;
+       unsigned next_proto_neg_len;
+#endif
+       unsigned char *exportedkeymat;
 
-       if ((i=SSL_accept(con)) <= 0)
+
+       i=SSL_accept(con);
+#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",srp_callback_parm.login);
+                       srp_callback_parm.user = SRP_VBASE_get_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");
+                       i=SSL_accept(con);
+               }
+#endif
+       if (i <= 0)
                {
                if (BIO_sock_should_retry(i))
                        {
@@ -2198,19 +2443,67 @@ static int init_ssl_connection(SSL *con)
                BIO_printf(bio_s_out,"Shared ciphers:%s\n",buf);
        str=SSL_CIPHER_get_name(SSL_get_current_cipher(con));
        BIO_printf(bio_s_out,"CIPHER is %s\n",(str != NULL)?str:"(NONE)");
-       if (con->hit) BIO_printf(bio_s_out,"Reused session-id\n");
+#if !defined(OPENSSL_NO_TLSEXT) && !defined(OPENSSL_NO_NEXTPROTONEG)
+       SSL_get0_next_proto_negotiated(con, &next_proto_neg, &next_proto_neg_len);
+       if (next_proto_neg)
+               {
+               BIO_printf(bio_s_out,"NEXTPROTO is ");
+               BIO_write(bio_s_out, next_proto_neg, next_proto_neg_len);
+               BIO_printf(bio_s_out, "\n");
+               }
+#endif
+       {
+       SRTP_PROTECTION_PROFILE *srtp_profile
+         = SSL_get_selected_srtp_profile(con);
+
+       if(srtp_profile)
+               BIO_printf(bio_s_out,"SRTP Extension negotiated, profile=%s\n",
+                          srtp_profile->name);
+       }
+       if (SSL_cache_hit(con)) BIO_printf(bio_s_out,"Reused session-id\n");
        if (SSL_ctrl(con,SSL_CTRL_GET_FLAGS,0,NULL) &
                TLS1_FLAGS_TLS_PADDING_BUG)
-               BIO_printf(bio_s_out,"Peer has incorrect TLSv1 block padding\n");
+               BIO_printf(bio_s_out,
+                          "Peer has incorrect TLSv1 block padding\n");
 #ifndef OPENSSL_NO_KRB5
-       if (con->kssl_ctx->client_princ != NULL)
+       client_princ = kssl_ctx_get0_client_princ(SSL_get0_kssl_ctx(con));
+       if (client_princ != NULL)
                {
                BIO_printf(bio_s_out,"Kerberos peer principal is %s\n",
-                       con->kssl_ctx->client_princ);
+                                                               client_princ);
                }
 #endif /* OPENSSL_NO_KRB5 */
        BIO_printf(bio_s_out, "Secure Renegotiation IS%s supported\n",
                      SSL_get_secure_renegotiation_support(con) ? "" : " NOT");
+       if (keymatexportlabel != NULL)
+               {
+               BIO_printf(bio_s_out, "Keying material exporter:\n");
+               BIO_printf(bio_s_out, "    Label: '%s'\n", keymatexportlabel);
+               BIO_printf(bio_s_out, "    Length: %i bytes\n",
+                          keymatexportlen);
+               exportedkeymat = OPENSSL_malloc(keymatexportlen);
+               if (exportedkeymat != NULL)
+                       {
+                       if (!SSL_export_keying_material(con, exportedkeymat,
+                                                       keymatexportlen,
+                                                       keymatexportlabel,
+                                                       strlen(keymatexportlabel),
+                                                       NULL, 0, 0))
+                               {
+                               BIO_printf(bio_s_out, "    Error\n");
+                               }
+                       else
+                               {
+                               BIO_printf(bio_s_out, "    Keying material: ");
+                               for (i=0; i<keymatexportlen; i++)
+                                       BIO_printf(bio_s_out, "%02X",
+                                                  exportedkeymat[i]);
+                               BIO_printf(bio_s_out, "\n");
+                               }
+                       OPENSSL_free(exportedkeymat);
+                       }
+               }
+
        return(1);
        }
 
@@ -2228,6 +2521,9 @@ err:
        return(ret);
        }
 #endif
+#ifndef OPENSSL_NO_KRB5
+       char *client_princ;
+#endif
 
 #if 0
 static int load_CA(SSL_CTX *ctx, char *file)
@@ -2258,6 +2554,9 @@ static int www_body(char *hostname, int s, unsigned char *context)
        SSL *con;
        const SSL_CIPHER *c;
        BIO *io,*ssl_bio,*sbio;
+#ifndef OPENSSL_NO_KRB5
+       KSSL_CTX *kctx;
+#endif
 
        buf=OPENSSL_malloc(bufsize);
        if (buf == NULL) return(0);
@@ -2289,10 +2588,10 @@ static int www_body(char *hostname, int s, unsigned char *context)
                        }
 #endif
 #ifndef OPENSSL_NO_KRB5
-       if ((con->kssl_ctx = kssl_ctx_new()) != NULL)
+       if ((kctx = kssl_ctx_new()) != NULL)
                {
-               kssl_ctx_setstring(con->kssl_ctx, KSSL_SERVICE, KRB5SVC);
-               kssl_ctx_setstring(con->kssl_ctx, KSSL_KEYTAB, KRB5KEYTAB);
+               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,
@@ -2318,7 +2617,7 @@ static int www_body(char *hostname, int s, unsigned char *context)
 
        if (s_debug)
                {
-               con->debug=1;
+               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);
                }
@@ -2333,7 +2632,18 @@ static int www_body(char *hostname, int s, unsigned char *context)
                if (hack)
                        {
                        i=SSL_accept(con);
-
+#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",srp_callback_parm.login);
+                       srp_callback_parm.user = SRP_VBASE_get_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");
+                       i=SSL_accept(con);
+               }
+#endif
                        switch (SSL_get_error(con,i))
                                {
                        case SSL_ERROR_NONE:
@@ -2439,7 +2749,7 @@ static int www_body(char *hostname, int s, unsigned char *context)
                                        }
                                BIO_puts(io,"\n");
                                }
-                       BIO_printf(io,((con->hit)
+                       BIO_printf(io,(SSL_cache_hit(con)
                                ?"---\nReused, "
                                :"---\nNew, "));
                        c=SSL_get_current_cipher(con);
index c08544a..380efdb 100644 (file)
@@ -238,11 +238,10 @@ int init_client(int *sock, char *host, int port, int type)
        {
        unsigned char ip[4];
 
+       memset(ip, '\0', sizeof ip);
        if (!host_ip(host,&(ip[0])))
-               {
-               return(0);
-               }
-       return(init_client_ip(sock,ip,port,type));
+               return 0;
+       return init_client_ip(sock,ip,port,type);
        }
 
 static int init_client_ip(int *sock, unsigned char ip[4], int port, int type)
index b99179f..b16686c 100644 (file)
@@ -90,6 +90,7 @@ int MAIN(int, char **);
 int MAIN(int argc, char **argv)
        {
        SSL_SESSION *x=NULL;
+       X509 *peer = NULL;
        int ret=1,i,num,badops=0;
        BIO *out=NULL;
        int informat,outformat;
@@ -163,16 +164,17 @@ bad:
        ERR_load_crypto_strings();
        x=load_sess_id(infile,informat);
        if (x == NULL) { goto end; }
+       peer = SSL_SESSION_get0_peer(x);
 
        if(context)
            {
-           x->sid_ctx_length=strlen(context);
-           if(x->sid_ctx_length > SSL_MAX_SID_CTX_LENGTH)
+           size_t ctx_len = strlen(context);
+           if(ctx_len > SSL_MAX_SID_CTX_LENGTH)
                {
                BIO_printf(bio_err,"Context too long\n");
                goto end;
                }
-           memcpy(x->sid_ctx,context,x->sid_ctx_length);
+           SSL_SESSION_set1_id_context(x, (unsigned char *)context, ctx_len);
            }
 
 #ifdef undef
@@ -231,10 +233,10 @@ bad:
 
                if (cert)
                        {
-                       if (x->peer == NULL)
+                       if (peer == NULL)
                                BIO_puts(out,"No certificate present\n");
                        else
-                               X509_print(out,x->peer);
+                               X509_print(out,peer);
                        }
                }
 
@@ -253,12 +255,12 @@ bad:
                        goto end;
                        }
                }
-       else if (!noout && (x->peer != NULL)) /* just print the certificate */
+       else if (!noout && (peer != NULL)) /* just print the certificate */
                {
                if      (outformat == FORMAT_ASN1)
-                       i=(int)i2d_X509_bio(out,x->peer);
+                       i=(int)i2d_X509_bio(out,peer);
                else if (outformat == FORMAT_PEM)
-                       i=PEM_write_bio_X509(out,x->peer);
+                       i=PEM_write_bio_X509(out,peer);
                else    {
                        BIO_printf(bio_err,"bad output format specified for outfile\n");
                        goto end;
index 65f85fe..8358b12 100644 (file)
 #include <signal.h>
 #endif
 
-#ifdef _WIN32
+#if defined(_WIN32) || defined(__CYGWIN__)
 #include <windows.h>
+# if defined(__CYGWIN__) && !defined(_WIN32)
+  /* <windows.h> should define _WIN32, which normally is mutually
+   * exclusive with __CYGWIN__, but if it didn't... */
+#  define _WIN32
+  /* this is done because Cygwin alarm() fails sometimes. */
+# endif
 #endif
 
 #include <openssl/bn.h>
 #ifndef OPENSSL_NO_ECDH
 #include <openssl/ecdh.h>
 #endif
+#include <openssl/modes.h>
+
+#ifdef OPENSSL_FIPS
+#ifdef OPENSSL_DOING_MAKEDEPEND
+#undef AES_set_encrypt_key
+#undef AES_set_decrypt_key
+#undef DES_set_key_unchecked
+#endif
+#define BF_set_key     private_BF_set_key
+#define CAST_set_key   private_CAST_set_key
+#define idea_set_encrypt_key   private_idea_set_encrypt_key
+#define SEED_set_key   private_SEED_set_key
+#define RC2_set_key    private_RC2_set_key
+#define RC4_set_key    private_RC4_set_key
+#define DES_set_key_unchecked  private_DES_set_key_unchecked
+#define AES_set_encrypt_key    private_AES_set_encrypt_key
+#define AES_set_decrypt_key    private_AES_set_decrypt_key
+#define Camellia_set_key       private_Camellia_set_key
+#endif
 
 #ifndef HAVE_FORK
 # if defined(OPENSSL_SYS_VMS) || defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_MACINTOSH_CLASSIC) || defined(OPENSSL_SYS_OS2) || defined(OPENSSL_SYS_NETWARE)
@@ -214,7 +239,7 @@ static void print_result(int alg,int run_no,int count,double time_used);
 static int do_multi(int multi);
 #endif
 
-#define ALGOR_NUM      29
+#define ALGOR_NUM      30
 #define SIZE_NUM       5
 #define RSA_NUM                4
 #define DSA_NUM                3
@@ -229,7 +254,7 @@ static const char *names[ALGOR_NUM]={
   "aes-128 cbc","aes-192 cbc","aes-256 cbc",
   "camellia-128 cbc","camellia-192 cbc","camellia-256 cbc",
   "evp","sha256","sha512","whirlpool",
-  "aes-128 ige","aes-192 ige","aes-256 ige"};
+  "aes-128 ige","aes-192 ige","aes-256 ige","ghash"};
 static double results[ALGOR_NUM][SIZE_NUM];
 static int lengths[SIZE_NUM]={16,64,256,1024,8*1024};
 #ifndef OPENSSL_NO_RSA
@@ -273,9 +298,12 @@ static SIGRETTYPE sig_done(int sig)
 
 #if defined(_WIN32)
 
+#if !defined(SIGALRM)
 #define SIGALRM
+#endif
 static unsigned int lapse,schlock;
-static void alarm(unsigned int secs) { lapse = secs*1000; }
+static void alarm_win32(unsigned int secs) { lapse = secs*1000; }
+#define alarm alarm_win32
 
 static DWORD WINAPI sleepy(VOID *arg)
        {
@@ -469,6 +497,7 @@ int MAIN(int argc, char **argv)
 #define D_IGE_128_AES   26
 #define D_IGE_192_AES   27
 #define D_IGE_256_AES   28
+#define D_GHASH                29
        double d=0.0;
        long c[ALGOR_NUM][SIZE_NUM];
 #define        R_DSA_512       0
@@ -894,6 +923,10 @@ int MAIN(int argc, char **argv)
                        doit[D_CBC_192_AES]=1;
                        doit[D_CBC_256_AES]=1;
                        }
+               else if (strcmp(*argv,"ghash") == 0)
+                       {
+                       doit[D_GHASH]=1;
+                       }
                else
 #endif
 #ifndef OPENSSL_NO_CAMELLIA
@@ -1264,6 +1297,7 @@ int MAIN(int argc, char **argv)
        c[D_IGE_128_AES][0]=count;
        c[D_IGE_192_AES][0]=count;
        c[D_IGE_256_AES][0]=count;
+       c[D_GHASH][0]=count;
 
        for (i=1; i<SIZE_NUM; i++)
                {
@@ -1458,7 +1492,7 @@ int MAIN(int argc, char **argv)
 # error "You cannot disable DES on systems without SIGALRM."
 #endif /* OPENSSL_NO_DES */
 #else
-#define COND(c)        (run)
+#define COND(c)        (run && count<0x7fffffff)
 #define COUNT(d) (count)
 #ifndef _WIN32
        signal(SIGALRM,sig_done);
@@ -1754,7 +1788,22 @@ int MAIN(int argc, char **argv)
                        print_result(D_IGE_256_AES,j,count,d);
                        }
                }
+       if (doit[D_GHASH])
+               {
+               GCM128_CONTEXT *ctx = CRYPTO_gcm128_new(&aes_ks1,(block128_f)AES_encrypt);
+               CRYPTO_gcm128_setiv (ctx,(unsigned char *)"0123456789ab",12);
 
+               for (j=0; j<SIZE_NUM; j++)
+                       {
+                       print_message(names[D_GHASH],c[D_GHASH][j],lengths[j]);
+                       Time_F(START);
+                       for (count=0,run=1; COND(c[D_GHASH][j]); count++)
+                               CRYPTO_gcm128_aad(ctx,buf,lengths[j]);
+                       d=Time_F(STOP);
+                       print_result(D_GHASH,j,count,d);
+                       }
+               CRYPTO_gcm128_release(ctx);
+               }
 
 #endif
 #ifndef OPENSSL_NO_CAMELLIA
@@ -2548,7 +2597,7 @@ static void pkey_print_message(const char *str, const char *str2, long num,
        BIO_printf(bio_err,mr ? "+DTP:%d:%s:%s:%d\n"
                           : "Doing %d bit %s %s's for %ds: ",bits,str,str2,tm);
        (void)BIO_flush(bio_err);
-       alarm(RSA_SECONDS);
+       alarm(tm);
 #else
        BIO_printf(bio_err,mr ? "+DNP:%ld:%d:%s:%s\n"
                           : "Doing %ld %d bit %s %s's: ",num,bits,str,str2);
@@ -2608,7 +2657,11 @@ static int do_multi(int multi)
        fds=malloc(multi*sizeof *fds);
        for(n=0 ; n < multi ; ++n)
                {
-               pipe(fd);
+               if (pipe(fd) == -1)
+                       {
+                       fprintf(stderr, "pipe failure\n");
+                       exit(1);
+                       }
                fflush(stdout);
                fflush(stderr);
                if(fork())
@@ -2620,7 +2673,11 @@ static int do_multi(int multi)
                        {
                        close(fd[0]);
                        close(1);
-                       dup(fd[1]);
+                       if (dup(fd[1]) == -1)
+                               {
+                               fprintf(stderr, "dup failed\n");
+                               exit(1);
+                               }
                        close(fd[1]);
                        mr=1;
                        usertime=0;
diff --git a/crypto/openssl/apps/srp.c b/crypto/openssl/apps/srp.c
new file mode 100644 (file)
index 0000000..80e1b8a
--- /dev/null
@@ -0,0 +1,756 @@
+/* apps/srp.c */
+/* Written by Peter Sylvester (peter.sylvester@edelweb.fr)  
+ * for the EdelKey project and contributed to the OpenSSL project 2004.
+ */
+/* ====================================================================
+ * Copyright (c) 2004 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer. 
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+#include <openssl/opensslconf.h>
+
+#ifndef OPENSSL_NO_SRP
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <openssl/conf.h>
+#include <openssl/bio.h>
+#include <openssl/err.h>
+#include <openssl/txt_db.h>
+#include <openssl/buffer.h>
+#include <openssl/srp.h>
+
+#include "apps.h"
+
+#undef PROG
+#define PROG srp_main
+
+#define BASE_SECTION   "srp"
+#define CONFIG_FILE "openssl.cnf"
+
+#define ENV_RANDFILE           "RANDFILE"
+
+#define ENV_DATABASE           "srpvfile"
+#define ENV_DEFAULT_SRP                "default_srp"
+
+static char *srp_usage[]={
+"usage: srp [args] [user] \n",
+"\n",
+" -verbose        Talk alot while doing things\n",
+" -config file    A config file\n",
+" -name arg       The particular srp definition to use\n",
+" -srpvfile arg   The srp verifier file name\n",
+" -add            add an user and srp verifier\n",
+" -modify         modify the srp verifier of an existing user\n",
+" -delete         delete user from verifier file\n",
+" -list           list user\n",
+" -gn arg         g and N values to be used for new verifier\n",
+" -userinfo arg   additional info to be set for user\n",
+" -passin arg     input file pass phrase source\n",
+" -passout arg    output file pass phrase source\n",
+#ifndef OPENSSL_NO_ENGINE
+" -engine e         - use engine e, possibly a hardware device.\n",
+#endif
+NULL
+};
+
+#ifdef EFENCE
+extern int EF_PROTECT_FREE;
+extern int EF_PROTECT_BELOW;
+extern int EF_ALIGNMENT;
+#endif
+
+static CONF *conf=NULL;
+static char *section=NULL;
+
+#define VERBOSE if (verbose) 
+#define VVERBOSE if (verbose>1) 
+
+
+int MAIN(int, char **);
+
+static int get_index(CA_DB *db, char* id, char type)
+       {
+       char ** pp;
+       int i;
+       if (id == NULL) return -1;
+       if (type == DB_SRP_INDEX) 
+       for (i = 0; i < sk_OPENSSL_PSTRING_num(db->db->data); i++)
+               {
+               pp = (char **)sk_OPENSSL_PSTRING_value(db->db->data, i);
+               if (pp[DB_srptype][0] == DB_SRP_INDEX  && !strcmp(id, pp[DB_srpid])) 
+                       return i;
+               }
+       else for (i = 0; i < sk_OPENSSL_PSTRING_num(db->db->data); i++)
+               {
+               pp = (char **)sk_OPENSSL_PSTRING_value(db->db->data, i);
+
+               if (pp[DB_srptype][0] != DB_SRP_INDEX && !strcmp(id,pp[DB_srpid])) 
+                       return i;
+               }
+
+       return -1 ; 
+       }
+
+static void print_entry(CA_DB *db, BIO *bio, int indx, int verbose, char *s)
+       {
+       if (indx >= 0 && verbose)
+               {
+               int j;
+               char **pp = (char **)sk_OPENSSL_PSTRING_value(db->db->data, indx);
+               BIO_printf(bio, "%s \"%s\"\n", s, pp[DB_srpid]);
+               for (j = 0; j < DB_NUMBER; j++)
+                       {
+                       BIO_printf(bio_err,"  %d = \"%s\"\n", j, pp[j]);
+                       }
+               }
+       }
+
+static void print_index(CA_DB *db, BIO *bio, int indexindex, int verbose)
+       {
+       print_entry(db, bio, indexindex, verbose, "g N entry") ;
+       }
+
+static void print_user(CA_DB *db, BIO *bio, int userindex, int verbose)
+       {
+       if (verbose > 0)
+               {
+               char **pp = (char **)sk_OPENSSL_PSTRING_value(db->db->data, userindex);
+
+               if (pp[DB_srptype][0] != 'I')
+                       {
+                       print_entry(db, bio, userindex, verbose, "User entry");
+                       print_entry(db, bio, get_index(db, pp[DB_srpgN], 'I'), verbose, "g N entry");
+                       }
+
+               }
+       }
+
+static int update_index(CA_DB *db, BIO *bio, char **row)
+       {
+       char ** irow;
+       int i;
+
+       if ((irow=(char **)OPENSSL_malloc(sizeof(char *)*(DB_NUMBER+1))) == NULL)
+               {
+               BIO_printf(bio_err,"Memory allocation failure\n");
+               return 0;
+               }
+
+       for (i=0; i<DB_NUMBER; i++)
+               {
+               irow[i]=row[i];
+               row[i]=NULL;
+               }
+       irow[DB_NUMBER]=NULL;
+
+       if (!TXT_DB_insert(db->db,irow))
+               {
+               BIO_printf(bio,"failed to update srpvfile\n");
+               BIO_printf(bio,"TXT_DB error number %ld\n",db->db->error);
+               OPENSSL_free(irow);
+               return 0;
+               }
+       return 1;
+       }
+
+static void lookup_fail(const char *name, char *tag)
+       {
+       BIO_printf(bio_err,"variable lookup failed for %s::%s\n",name,tag);
+       }
+
+
+static char *srp_verify_user(const char *user, const char *srp_verifier,
+                            char *srp_usersalt, const char *g, const char *N,
+                            const char *passin, BIO *bio, int verbose)
+       {
+       char password[1024];
+       PW_CB_DATA cb_tmp;
+       char *verifier = NULL;
+       char *gNid = NULL;
+
+       cb_tmp.prompt_info = user;
+       cb_tmp.password = passin;
+
+       if (password_callback(password, 1024, 0, &cb_tmp) >0)
+               {
+               VERBOSE BIO_printf(bio,"Validating\n   user=\"%s\"\n srp_verifier=\"%s\"\n srp_usersalt=\"%s\"\n g=\"%s\"\n N=\"%s\"\n",user,srp_verifier,srp_usersalt, g, N);
+               BIO_printf(bio, "Pass %s\n", password);
+
+               if (!(gNid=SRP_create_verifier(user, password, &srp_usersalt, &verifier, N, g)))
+                       {
+                       BIO_printf(bio, "Internal error validating SRP verifier\n");
+                       }
+               else
+                       {
+                       if (strcmp(verifier, srp_verifier))
+                               gNid = NULL;
+                       OPENSSL_free(verifier);
+                       }
+               }
+       return gNid;
+       }
+
+static char *srp_create_user(char *user, char **srp_verifier,
+                            char **srp_usersalt, char *g, char *N,
+                            char *passout, BIO *bio, int verbose)
+       {
+       char password[1024];
+        PW_CB_DATA cb_tmp;
+       char *gNid = NULL;
+       char *salt = NULL;
+        cb_tmp.prompt_info = user;
+        cb_tmp.password = passout;
+
+       if (password_callback(password,1024,1,&cb_tmp) >0)
+               {
+               VERBOSE BIO_printf(bio,"Creating\n user=\"%s\"\n g=\"%s\"\n N=\"%s\"\n",user,g,N);
+               if (!(gNid =SRP_create_verifier(user, password, &salt, srp_verifier, N, g)))
+                       {
+                       BIO_printf(bio,"Internal error creating SRP verifier\n");
+                       }
+               else 
+                       *srp_usersalt = salt;
+               VVERBOSE BIO_printf(bio,"gNid=%s salt =\"%s\"\n verifier =\"%s\"\n", gNid,salt, *srp_verifier);
+
+               }
+       return gNid;
+       }
+
+int MAIN(int argc, char **argv)
+       {
+       int add_user = 0;
+       int list_user= 0;
+       int delete_user= 0;
+       int modify_user= 0;
+       char * user = NULL;
+
+       char *passargin = NULL, *passargout = NULL;
+       char *passin = NULL, *passout = NULL;
+        char * gN = NULL;
+       int gNindex = -1;
+       char ** gNrow = NULL;
+       int maxgN = -1;
+
+       char * userinfo = NULL;
+
+       int badops=0;
+       int ret=1;
+       int errors=0;
+       int verbose=0;
+       int doupdatedb=0;
+       char *configfile=NULL;
+       char *dbfile=NULL;
+       CA_DB *db=NULL;
+       char **pp ;
+       int i;
+       long errorline = -1;
+       char *randfile=NULL;
+#ifndef OPENSSL_NO_ENGINE
+       char *engine = NULL;
+#endif
+       char *tofree=NULL;
+       DB_ATTR db_attr;
+
+#ifdef EFENCE
+EF_PROTECT_FREE=1;
+EF_PROTECT_BELOW=1;
+EF_ALIGNMENT=0;
+#endif
+
+       apps_startup();
+
+       conf = NULL;
+       section = NULL;
+
+       if (bio_err == NULL)
+               if ((bio_err=BIO_new(BIO_s_file())) != NULL)
+                       BIO_set_fp(bio_err,stderr,BIO_NOCLOSE|BIO_FP_TEXT);
+
+       argc--;
+       argv++;
+       while (argc >= 1 && badops == 0)
+               {
+               if      (strcmp(*argv,"-verbose") == 0)
+                       verbose++;
+               else if (strcmp(*argv,"-config") == 0)
+                       {
+                       if (--argc < 1) goto bad;
+                       configfile= *(++argv);
+                       }
+               else if (strcmp(*argv,"-name") == 0)
+                       {
+                       if (--argc < 1) goto bad;
+                       section= *(++argv);
+                       }
+               else if (strcmp(*argv,"-srpvfile") == 0)
+                       {
+                       if (--argc < 1) goto bad;
+                       dbfile= *(++argv);
+                       }
+               else if (strcmp(*argv,"-add") == 0)
+                       add_user=1;
+               else if (strcmp(*argv,"-delete") == 0)
+                       delete_user=1;
+               else if (strcmp(*argv,"-modify") == 0)
+                       modify_user=1;
+               else if (strcmp(*argv,"-list") == 0)
+                       list_user=1;
+               else if (strcmp(*argv,"-gn") == 0)
+                       {
+                       if (--argc < 1) goto bad;
+                       gN= *(++argv);
+                       }
+               else if (strcmp(*argv,"-userinfo") == 0)
+                       {
+                       if (--argc < 1) goto bad;
+                       userinfo= *(++argv);
+                       }
+               else if (strcmp(*argv,"-passin") == 0)
+                       {
+                       if (--argc < 1) goto bad;
+                       passargin= *(++argv);
+                       }
+               else if (strcmp(*argv,"-passout") == 0)
+                       {
+                       if (--argc < 1) goto bad;
+                       passargout= *(++argv);
+                       }
+#ifndef OPENSSL_NO_ENGINE
+               else if (strcmp(*argv,"-engine") == 0)
+                       {
+                       if (--argc < 1) goto bad;
+                       engine= *(++argv);
+                       }
+#endif
+
+               else if (**argv == '-')
+                       {
+bad:
+                       BIO_printf(bio_err,"unknown option %s\n",*argv);
+                       badops=1;
+                       break;
+                       }
+               else 
+                       break;
+       
+               argc--;
+               argv++;
+               }
+
+       if (dbfile && configfile)
+               {
+               BIO_printf(bio_err,"-dbfile and -configfile cannot be specified together.\n");
+               badops = 1;
+               }
+       if (add_user+delete_user+modify_user+list_user != 1)
+               {
+               BIO_printf(bio_err,"Exactly one of the options -add, -delete, -modify -list must be specified.\n");
+               badops = 1;
+               }
+       if (delete_user+modify_user+delete_user== 1 && argc <= 0)
+               {
+               BIO_printf(bio_err,"Need at least one user for options -add, -delete, -modify. \n");
+               badops = 1;
+               }
+       if ((passin || passout) && argc != 1 )
+               {
+               BIO_printf(bio_err,"-passin, -passout arguments only valid with one user.\n");
+               badops = 1;
+               }
+
+       if (badops)
+               {
+               for (pp=srp_usage; (*pp != NULL); pp++)
+                       BIO_printf(bio_err,"%s",*pp);
+
+               BIO_printf(bio_err," -rand file%cfile%c...\n", LIST_SEPARATOR_CHAR, LIST_SEPARATOR_CHAR);
+               BIO_printf(bio_err,"                 load the file (or the files in the directory) into\n");
+               BIO_printf(bio_err,"                 the random number generator\n");
+               goto err;
+               }
+
+       ERR_load_crypto_strings();
+
+#ifndef OPENSSL_NO_ENGINE
+       setup_engine(bio_err, engine, 0);
+#endif
+
+       if(!app_passwd(bio_err, passargin, passargout, &passin, &passout))
+               {
+               BIO_printf(bio_err, "Error getting passwords\n");
+               goto err;
+               }
+
+        if (!dbfile)
+               {
+
+
+       /*****************************************************************/
+               tofree=NULL;
+               if (configfile == NULL) configfile = getenv("OPENSSL_CONF");
+               if (configfile == NULL) configfile = getenv("SSLEAY_CONF");
+               if (configfile == NULL)
+                       {
+                       const char *s=X509_get_default_cert_area();
+                       size_t len;
+
+#ifdef OPENSSL_SYS_VMS
+                       len = strlen(s)+sizeof(CONFIG_FILE);
+                       tofree=OPENSSL_malloc(len);
+                       strcpy(tofree,s);
+#else
+                       len = strlen(s)+sizeof(CONFIG_FILE)+1;
+                       tofree=OPENSSL_malloc(len);
+                       BUF_strlcpy(tofree,s,len);
+                       BUF_strlcat(tofree,"/",len);
+#endif
+                       BUF_strlcat(tofree,CONFIG_FILE,len);
+                       configfile=tofree;
+                       }
+
+               VERBOSE BIO_printf(bio_err,"Using configuration from %s\n",configfile);
+               conf = NCONF_new(NULL);
+               if (NCONF_load(conf,configfile,&errorline) <= 0)
+                       {
+                       if (errorline <= 0)
+                               BIO_printf(bio_err,"error loading the config file '%s'\n",
+                                       configfile);
+                       else
+                               BIO_printf(bio_err,"error on line %ld of config file '%s'\n"
+                                       ,errorline,configfile);
+                       goto err;
+                       }
+               if(tofree)
+                       {
+                       OPENSSL_free(tofree);
+                       tofree = NULL;
+                       }
+
+               if (!load_config(bio_err, conf))
+                       goto err;
+
+       /* Lets get the config section we are using */
+               if (section == NULL)
+                       {
+                       VERBOSE BIO_printf(bio_err,"trying to read " ENV_DEFAULT_SRP " in \" BASE_SECTION \"\n");
+
+                       section=NCONF_get_string(conf,BASE_SECTION,ENV_DEFAULT_SRP);
+                       if (section == NULL)
+                               {
+                               lookup_fail(BASE_SECTION,ENV_DEFAULT_SRP);
+                               goto err;
+                               }
+                       }
+         
+               if (randfile == NULL && conf)
+                       randfile = NCONF_get_string(conf, BASE_SECTION, "RANDFILE");
+
+       
+               VERBOSE BIO_printf(bio_err,"trying to read " ENV_DATABASE " in section \"%s\"\n",section);
+
+               if ((dbfile=NCONF_get_string(conf,section,ENV_DATABASE)) == NULL)
+                       {
+                       lookup_fail(section,ENV_DATABASE);
+                       goto err;
+                       }
+
+               }
+       if (randfile == NULL)
+               ERR_clear_error();
+               else 
+               app_RAND_load_file(randfile, bio_err, 0);
+
+       VERBOSE BIO_printf(bio_err,"Trying to read SRP verifier file \"%s\"\n",dbfile);
+
+       db = load_index(dbfile, &db_attr);
+       if (db == NULL) goto err;
+
+       /* Lets check some fields */
+       for (i = 0; i < sk_OPENSSL_PSTRING_num(db->db->data); i++)
+               {
+               pp = (char **)sk_OPENSSL_PSTRING_value(db->db->data, i);
+       
+               if (pp[DB_srptype][0] == DB_SRP_INDEX)
+                       {
+                       maxgN = i;
+                       if (gNindex < 0 && gN != NULL && !strcmp(gN, pp[DB_srpid]))
+                               gNindex = i;
+
+                       print_index(db, bio_err, i, verbose > 1);
+                       }
+               }
+       
+       VERBOSE BIO_printf(bio_err, "Database initialised\n");
+
+       if (gNindex >= 0)
+               {
+               gNrow = (char **)sk_OPENSSL_PSTRING_value(db->db->data, gNindex);
+               print_entry(db, bio_err, gNindex, verbose > 1, "Default g and N") ;
+               }
+       else if (maxgN > 0 && !SRP_get_default_gN(gN))
+               {
+               BIO_printf(bio_err, "No g and N value for index \"%s\"\n", gN);
+               goto err;
+               }
+       else
+               {
+               VERBOSE BIO_printf(bio_err, "Database has no g N information.\n");
+               gNrow = NULL;
+               }
+       
+
+       VVERBOSE BIO_printf(bio_err,"Starting user processing\n");
+
+       if (argc > 0)
+               user = *(argv++) ;
+
+       while (list_user || user)
+               {
+               int userindex = -1;
+               if (user) 
+                       VVERBOSE BIO_printf(bio_err, "Processing user \"%s\"\n", user);
+               if ((userindex = get_index(db, user, 'U')) >= 0)
+                       {
+                       print_user(db, bio_err, userindex, (verbose > 0) || list_user);
+                       }
+               
+               if (list_user)
+                       {
+                       if (user == NULL)
+                               {
+                               BIO_printf(bio_err,"List all users\n");
+
+                               for (i = 0; i < sk_OPENSSL_PSTRING_num(db->db->data); i++)
+                                       {
+                                       print_user(db,bio_err, i, 1);
+                                       }
+                               list_user = 0;
+                               }
+                       else if (userindex < 0)
+                               {
+                               BIO_printf(bio_err, "user \"%s\" does not exist, ignored. t\n",
+                                          user);
+                               errors++;
+                               }
+                       }
+               else if (add_user)
+                       {
+                       if (userindex >= 0)
+                               {
+                               /* reactivation of a new user */
+                               char **row = (char **)sk_OPENSSL_PSTRING_value(db->db->data, userindex);
+                               BIO_printf(bio_err, "user \"%s\" reactivated.\n", user);
+                               row[DB_srptype][0] = 'V';
+
+                               doupdatedb = 1;
+                               }
+                       else
+                               {
+                               char *row[DB_NUMBER] ; char *gNid;
+                               row[DB_srpverifier] = NULL;
+                               row[DB_srpsalt] = NULL;
+                               row[DB_srpinfo] = NULL;
+                               if (!(gNid = srp_create_user(user,&(row[DB_srpverifier]), &(row[DB_srpsalt]),gNrow?gNrow[DB_srpsalt]:gN,gNrow?gNrow[DB_srpverifier]:NULL, passout, bio_err,verbose)))
+                                       {
+                                               BIO_printf(bio_err, "Cannot create srp verifier for user \"%s\", operation abandoned .\n", user);
+                                               errors++;
+                                               goto err;
+                                       }
+                               row[DB_srpid] = BUF_strdup(user);
+                               row[DB_srptype] = BUF_strdup("v");
+                               row[DB_srpgN] = BUF_strdup(gNid);
+
+                               if (!row[DB_srpid] || !row[DB_srpgN] || !row[DB_srptype] || !row[DB_srpverifier] || !row[DB_srpsalt] ||
+                                       (userinfo && (!(row[DB_srpinfo] = BUF_strdup(userinfo)))) || 
+                                       !update_index(db, bio_err, row))
+                                       {
+                                       if (row[DB_srpid]) OPENSSL_free(row[DB_srpid]);
+                                       if (row[DB_srpgN]) OPENSSL_free(row[DB_srpgN]);
+                                       if (row[DB_srpinfo]) OPENSSL_free(row[DB_srpinfo]);
+                                       if (row[DB_srptype]) OPENSSL_free(row[DB_srptype]);
+                                       if (row[DB_srpverifier]) OPENSSL_free(row[DB_srpverifier]);
+                                       if (row[DB_srpsalt]) OPENSSL_free(row[DB_srpsalt]);
+                                       goto err;
+                                       }
+                               doupdatedb = 1;
+                               }
+                       }
+               else if (modify_user)
+                       {
+                       if (userindex < 0)
+                               {
+                               BIO_printf(bio_err,"user \"%s\" does not exist, operation ignored.\n",user);
+                               errors++;
+                               }
+                       else
+                               {
+
+                               char **row = (char **)sk_OPENSSL_PSTRING_value(db->db->data, userindex);
+                               char type = row[DB_srptype][0];
+                               if (type == 'v')
+                                       {
+                                       BIO_printf(bio_err,"user \"%s\" already updated, operation ignored.\n",user);
+                                       errors++;
+                                       }
+                               else
+                                       {
+                                       char *gNid;
+
+                                       if (row[DB_srptype][0] == 'V')
+                                               {
+                                               int user_gN;
+                                               char **irow = NULL;
+                                               VERBOSE BIO_printf(bio_err,"Verifying password for user \"%s\"\n",user);
+                                               if ( (user_gN = get_index(db, row[DB_srpgN], DB_SRP_INDEX)) >= 0)
+                                                       irow = (char **)sk_OPENSSL_PSTRING_value(db->db->data, userindex);
+
+                                               if (!srp_verify_user(user, row[DB_srpverifier], row[DB_srpsalt], irow ? irow[DB_srpsalt] : row[DB_srpgN], irow ? irow[DB_srpverifier] : NULL, passin, bio_err, verbose))
+                                                       {
+                                                       BIO_printf(bio_err, "Invalid password for user \"%s\", operation abandoned.\n", user);
+                                                       errors++;
+                                                       goto err;
+                                                       }
+                                               } 
+                                       VERBOSE BIO_printf(bio_err,"Password for user \"%s\" ok.\n",user);
+
+                                       if (!(gNid=srp_create_user(user,&(row[DB_srpverifier]), &(row[DB_srpsalt]),gNrow?gNrow[DB_srpsalt]:NULL, gNrow?gNrow[DB_srpverifier]:NULL, passout, bio_err,verbose)))
+                                               {
+                                                       BIO_printf(bio_err, "Cannot create srp verifier for user \"%s\", operation abandoned.\n", user);
+                                                       errors++;
+                                                       goto err;
+                                               }
+
+                                       row[DB_srptype][0] = 'v';
+                                       row[DB_srpgN] = BUF_strdup(gNid);
+                                       if (!row[DB_srpid] || !row[DB_srpgN] || !row[DB_srptype] || !row[DB_srpverifier] || !row[DB_srpsalt] ||
+                                               (userinfo && (!(row[DB_srpinfo] = BUF_strdup(userinfo)))))  
+                                               goto err;
+
+                                       doupdatedb = 1;
+                                       }
+                               }
+                       }
+               else if (delete_user)
+                       {
+                       if (userindex < 0)
+                               {
+                               BIO_printf(bio_err, "user \"%s\" does not exist, operation ignored. t\n", user);
+                               errors++;
+                               }
+                       else
+                               {
+                               char **xpp = (char **)sk_OPENSSL_PSTRING_value(db->db->data, userindex);
+                               BIO_printf(bio_err, "user \"%s\" revoked. t\n", user);
+
+                               xpp[DB_srptype][0] = 'R';
+                               
+                               doupdatedb = 1;
+                               }
+                       }
+               if (--argc > 0)
+                       user = *(argv++) ;
+               else
+                       {
+                       user = NULL;
+                       list_user = 0;
+                       }
+               }
+
+       VERBOSE BIO_printf(bio_err,"User procession done.\n");
+
+
+       if (doupdatedb)
+               {
+               /* Lets check some fields */
+               for (i = 0; i < sk_OPENSSL_PSTRING_num(db->db->data); i++)
+                       {
+                       pp = (char **)sk_OPENSSL_PSTRING_value(db->db->data, i);
+       
+                       if (pp[DB_srptype][0] == 'v')
+                               {
+                               pp[DB_srptype][0] = 'V';
+                               print_user(db, bio_err, i, verbose);
+                               }
+                       }
+
+               VERBOSE BIO_printf(bio_err, "Trying to update srpvfile.\n");
+               if (!save_index(dbfile, "new", db)) goto err;
+                               
+               VERBOSE BIO_printf(bio_err, "Temporary srpvfile created.\n");
+               if (!rotate_index(dbfile, "new", "old")) goto err;
+
+               VERBOSE BIO_printf(bio_err, "srpvfile updated.\n");
+               }
+
+       ret = (errors != 0);
+err:
+       if (errors != 0)
+       VERBOSE BIO_printf(bio_err,"User errors %d.\n",errors);
+
+       VERBOSE BIO_printf(bio_err,"SRP terminating with code %d.\n",ret);
+       if(tofree)
+               OPENSSL_free(tofree);
+       if (ret) ERR_print_errors(bio_err);
+       if (randfile) app_RAND_write_file(randfile, bio_err);
+       if (conf) NCONF_free(conf);
+       if (db) free_index(db);
+
+       OBJ_cleanup();
+       apps_shutdown();
+       OPENSSL_EXIT(ret);
+       }
+
+
+
+#endif
+
index 9163997..b9749dc 100644 (file)
@@ -230,6 +230,7 @@ int MAIN(int argc, char **argv)
 end:
        if (ret == 1) {
                BIO_printf(bio_err,"usage: verify [-verbose] [-CApath path] [-CAfile file] [-purpose purpose] [-crl_check]");
+               BIO_printf(bio_err," [-attime timestamp]");
 #ifndef OPENSSL_NO_ENGINE
                BIO_printf(bio_err," [-engine e]");
 #endif
index 9f5eaeb..e6e5e0d 100644 (file)
@@ -157,9 +157,10 @@ static int MS_CALLBACK callb(int ok, X509_STORE_CTX *ctx);
 static int sign (X509 *x, EVP_PKEY *pkey,int days,int clrext, const EVP_MD *digest,
                                                CONF *conf, char *section);
 static int x509_certify (X509_STORE *ctx,char *CAfile,const EVP_MD *digest,
-                        X509 *x,X509 *xca,EVP_PKEY *pkey,char *serial,
-                        int create,int days, int clrext, CONF *conf, char *section,
-                                               ASN1_INTEGER *sno);
+                        X509 *x,X509 *xca,EVP_PKEY *pkey,
+                        STACK_OF(OPENSSL_STRING) *sigopts,
+                        char *serial, int create ,int days, int clrext,
+                        CONF *conf, char *section, ASN1_INTEGER *sno);
 static int purpose_print(BIO *bio, X509 *cert, X509_PURPOSE *pt);
 static int reqfile=0;
 
@@ -172,6 +173,7 @@ int MAIN(int argc, char **argv)
        X509_REQ *req=NULL;
        X509 *x=NULL,*xca=NULL;
        ASN1_OBJECT *objtmp;
+       STACK_OF(OPENSSL_STRING) *sigopts = NULL;
        EVP_PKEY *Upkey=NULL,*CApkey=NULL;
        ASN1_INTEGER *sno = NULL;
        int i,num,badops=0;
@@ -271,6 +273,15 @@ int MAIN(int argc, char **argv)
                        if (--argc < 1) goto bad;
                        CAkeyformat=str2fmt(*(++argv));
                        }
+               else if (strcmp(*argv,"-sigopt") == 0)
+                       {
+                       if (--argc < 1)
+                               goto bad;
+                       if (!sigopts)
+                               sigopts = sk_OPENSSL_STRING_new_null();
+                       if (!sigopts || !sk_OPENSSL_STRING_push(sigopts, *(++argv)))
+                               goto bad;
+                       }
                else if (strcmp(*argv,"-days") == 0)
                        {
                        if (--argc < 1) goto bad;
@@ -970,7 +981,8 @@ bad:
                                
                                assert(need_rand);
                                if (!x509_certify(ctx,CAfile,digest,x,xca,
-                                       CApkey, CAserial,CA_createserial,days, clrext,
+                                       CApkey, sigopts,
+                                       CAserial,CA_createserial,days, clrext,
                                        extconf, extsect, sno))
                                        goto end;
                                }
@@ -1081,6 +1093,8 @@ end:
        X509_free(xca);
        EVP_PKEY_free(Upkey);
        EVP_PKEY_free(CApkey);
+       if (sigopts)
+               sk_OPENSSL_STRING_free(sigopts);
        X509_REQ_free(rq);
        ASN1_INTEGER_free(sno);
        sk_ASN1_OBJECT_pop_free(trust, ASN1_OBJECT_free);
@@ -1131,8 +1145,11 @@ static ASN1_INTEGER *x509_load_serial(char *CAfile, char *serialfile, int create
        }
 
 static int x509_certify(X509_STORE *ctx, char *CAfile, const EVP_MD *digest,
-            X509 *x, X509 *xca, EVP_PKEY *pkey, char *serialfile, int create,
-            int days, int clrext, CONF *conf, char *section, ASN1_INTEGER *sno)
+                       X509 *x, X509 *xca, EVP_PKEY *pkey,
+                       STACK_OF(OPENSSL_STRING) *sigopts,
+                       char *serialfile, int create,
+                       int days, int clrext, CONF *conf, char *section,
+                       ASN1_INTEGER *sno)
        {
        int ret=0;
        ASN1_INTEGER *bs=NULL;
@@ -1191,7 +1208,8 @@ static int x509_certify(X509_STORE *ctx, char *CAfile, const EVP_MD *digest,
                 if (!X509V3_EXT_add_nconf(conf, &ctx2, section, x)) goto end;
                }
 
-       if (!X509_sign(x,pkey,digest)) goto end;
+       if (!do_X509_sign(bio_err, x, pkey, digest, sigopts))
+               goto end;
        ret=1;
 end:
        X509_STORE_CTX_cleanup(&xsc);
index d2c9973..031abf0 100644 (file)
@@ -90,6 +90,11 @@ int AES_set_encrypt_key(const unsigned char *userKey, const int bits,
 int AES_set_decrypt_key(const unsigned char *userKey, const int bits,
        AES_KEY *key);
 
+int private_AES_set_encrypt_key(const unsigned char *userKey, const int bits,
+       AES_KEY *key);
+int private_AES_set_decrypt_key(const unsigned char *userKey, const int bits,
+       AES_KEY *key);
+
 void AES_encrypt(const unsigned char *in, unsigned char *out,
        const AES_KEY *key);
 void AES_decrypt(const unsigned char *in, unsigned char *out,
index a7ec54f..8f5210a 100644 (file)
@@ -625,7 +625,7 @@ static const u32 rcon[] = {
 /**
  * Expand the cipher key into the encryption key schedule.
  */
-int AES_set_encrypt_key(const unsigned char *userKey, const int bits,
+int private_AES_set_encrypt_key(const unsigned char *userKey, const int bits,
                        AES_KEY *key) {
 
        u32 *rk;
@@ -726,7 +726,7 @@ int AES_set_encrypt_key(const unsigned char *userKey, const int bits,
 /**
  * Expand the cipher key into the decryption key schedule.
  */
-int AES_set_decrypt_key(const unsigned char *userKey, const int bits,
+int private_AES_set_decrypt_key(const unsigned char *userKey, const int bits,
                         AES_KEY *key) {
 
         u32 *rk;
@@ -734,7 +734,7 @@ int AES_set_decrypt_key(const unsigned char *userKey, const int bits,
        u32 temp;
 
        /* first, start with an encryption schedule */
-       status = AES_set_encrypt_key(userKey, bits, key);
+       status = private_AES_set_encrypt_key(userKey, bits, key);
        if (status < 0)
                return status;
 
@@ -1201,7 +1201,7 @@ static const u32 rcon[] = {
 /**
  * Expand the cipher key into the encryption key schedule.
  */
-int AES_set_encrypt_key(const unsigned char *userKey, const int bits,
+int private_AES_set_encrypt_key(const unsigned char *userKey, const int bits,
                        AES_KEY *key) {
        u32 *rk;
        int i = 0;
@@ -1301,7 +1301,7 @@ int AES_set_encrypt_key(const unsigned char *userKey, const int bits,
 /**
  * Expand the cipher key into the decryption key schedule.
  */
-int AES_set_decrypt_key(const unsigned char *userKey, const int bits,
+int private_AES_set_decrypt_key(const unsigned char *userKey, const int bits,
                         AES_KEY *key) {
 
         u32 *rk;
@@ -1309,7 +1309,7 @@ int AES_set_decrypt_key(const unsigned char *userKey, const int bits,
        u32 temp;
 
        /* first, start with an encryption schedule */
-       status = AES_set_encrypt_key(userKey, bits, key);
+       status = private_AES_set_encrypt_key(userKey, bits, key);
        if (status < 0)
                return status;
 
index 4fead1b..f083488 100644 (file)
@@ -50,6 +50,7 @@
  */
 
 #include <openssl/opensslv.h>
+#include <openssl/crypto.h>
 #include <openssl/aes.h>
 #include "aes_locl.h"
 
@@ -62,3 +63,23 @@ const char *AES_options(void) {
         return "aes(partial)";
 #endif
 }
+
+/* FIPS wrapper functions to block low level AES calls in FIPS mode */
+
+int AES_set_encrypt_key(const unsigned char *userKey, const int bits,
+                       AES_KEY *key)
+       {
+#ifdef OPENSSL_FIPS
+       fips_cipher_abort(AES);
+#endif
+       return private_AES_set_encrypt_key(userKey, bits, key);
+       }
+
+int AES_set_decrypt_key(const unsigned char *userKey, const int bits,
+                       AES_KEY *key)
+       {
+#ifdef OPENSSL_FIPS
+       fips_cipher_abort(AES);
+#endif
+       return private_AES_set_decrypt_key(userKey, bits, key);
+       }
index aab40e6..687ed81 100755 (executable)
@@ -39,7 +39,7 @@
 # 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 AES_set_[de|en]cryption_key.
+# 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
@@ -2854,12 +2854,12 @@ sub enckey()
     &set_label("exit");
 &function_end("_x86_AES_set_encrypt_key");
 
-# int AES_set_encrypt_key(const unsigned char *userKey, const int bits,
+# int private_AES_set_encrypt_key(const unsigned char *userKey, const int bits,
 #                        AES_KEY *key)
-&function_begin_B("AES_set_encrypt_key");
+&function_begin_B("private_AES_set_encrypt_key");
        &call   ("_x86_AES_set_encrypt_key");
        &ret    ();
-&function_end_B("AES_set_encrypt_key");
+&function_end_B("private_AES_set_encrypt_key");
 
 sub deckey()
 { my ($i,$key,$tp1,$tp2,$tp4,$tp8) = @_;
@@ -2916,9 +2916,9 @@ sub deckey()
        &mov    (&DWP(4*$i,$key),$tp1);
 }
 
-# int AES_set_decrypt_key(const unsigned char *userKey, const int bits,
+# int private_AES_set_decrypt_key(const unsigned char *userKey, const int bits,
 #                        AES_KEY *key)
-&function_begin_B("AES_set_decrypt_key");
+&function_begin_B("private_AES_set_decrypt_key");
        &call   ("_x86_AES_set_encrypt_key");
        &cmp    ("eax",0);
        &je     (&label("proceed"));
@@ -2974,7 +2974,7 @@ sub deckey()
        &jb     (&label("permute"));
 
        &xor    ("eax","eax");                  # return success
-&function_end("AES_set_decrypt_key");
+&function_end("private_AES_set_decrypt_key");
 &asciz("AES for x86, CRYPTOGAMS by <appro\@openssl.org>");
 
 &asm_finish();
index a545e89..48fa857 100755 (executable)
@@ -588,6 +588,9 @@ $code.=<<___;
 .globl AES_encrypt
 .type  AES_encrypt,\@function,3
 .align 16
+.globl asm_AES_encrypt
+.hidden        asm_AES_encrypt
+asm_AES_encrypt:
 AES_encrypt:
        push    %rbx
        push    %rbp
@@ -1184,6 +1187,9 @@ $code.=<<___;
 .globl AES_decrypt
 .type  AES_decrypt,\@function,3
 .align 16
+.globl asm_AES_decrypt
+.hidden        asm_AES_decrypt
+asm_AES_decrypt:
 AES_decrypt:
        push    %rbx
        push    %rbp
@@ -1277,13 +1283,13 @@ $code.=<<___;
 ___
 }
 
-# int AES_set_encrypt_key(const unsigned char *userKey, const int bits,
+# int private_AES_set_encrypt_key(const unsigned char *userKey, const int bits,
 #                        AES_KEY *key)
 $code.=<<___;
-.globl AES_set_encrypt_key
-.type  AES_set_encrypt_key,\@function,3
+.globl private_AES_set_encrypt_key
+.type  private_AES_set_encrypt_key,\@function,3
 .align 16
-AES_set_encrypt_key:
+private_AES_set_encrypt_key:
        push    %rbx
        push    %rbp
        push    %r12                    # redundant, but allows to share 
@@ -1304,7 +1310,7 @@ AES_set_encrypt_key:
        add     \$56,%rsp
 .Lenc_key_epilogue:
        ret
-.size  AES_set_encrypt_key,.-AES_set_encrypt_key
+.size  private_AES_set_encrypt_key,.-private_AES_set_encrypt_key
 
 .type  _x86_64_AES_set_encrypt_key,\@abi-omnipotent
 .align 16
@@ -1547,13 +1553,13 @@ $code.=<<___;
 ___
 }
 
-# int AES_set_decrypt_key(const unsigned char *userKey, const int bits,
+# int private_AES_set_decrypt_key(const unsigned char *userKey, const int bits,
 #                        AES_KEY *key)
 $code.=<<___;
-.globl AES_set_decrypt_key
-.type  AES_set_decrypt_key,\@function,3
+.globl private_AES_set_decrypt_key
+.type  private_AES_set_decrypt_key,\@function,3
 .align 16
-AES_set_decrypt_key:
+private_AES_set_decrypt_key:
        push    %rbx
        push    %rbp
        push    %r12
@@ -1622,7 +1628,7 @@ $code.=<<___;
        add     \$56,%rsp
 .Ldec_key_epilogue:
        ret
-.size  AES_set_decrypt_key,.-AES_set_decrypt_key
+.size  private_AES_set_decrypt_key,.-private_AES_set_decrypt_key
 ___
 
 # void AES_cbc_encrypt (const void char *inp, unsigned char *out,
@@ -1648,6 +1654,9 @@ $code.=<<___;
 .type  AES_cbc_encrypt,\@function,6
 .align 16
 .extern        OPENSSL_ia32cap_P
+.globl asm_AES_cbc_encrypt
+.hidden        asm_AES_cbc_encrypt
+asm_AES_cbc_encrypt:
 AES_cbc_encrypt:
        cmp     \$0,%rdx        # check length
        je      .Lcbc_epilogue
@@ -2766,13 +2775,13 @@ cbc_se_handler:
        .rva    .LSEH_end_AES_decrypt
        .rva    .LSEH_info_AES_decrypt
 
-       .rva    .LSEH_begin_AES_set_encrypt_key
-       .rva    .LSEH_end_AES_set_encrypt_key
-       .rva    .LSEH_info_AES_set_encrypt_key
+       .rva    .LSEH_begin_private_AES_set_encrypt_key
+       .rva    .LSEH_end_private_AES_set_encrypt_key
+       .rva    .LSEH_info_private_AES_set_encrypt_key
 
-       .rva    .LSEH_begin_AES_set_decrypt_key
-       .rva    .LSEH_end_AES_set_decrypt_key
-       .rva    .LSEH_info_AES_set_decrypt_key
+       .rva    .LSEH_begin_private_AES_set_decrypt_key
+       .rva    .LSEH_end_private_AES_set_decrypt_key
+       .rva    .LSEH_info_private_AES_set_decrypt_key
 
        .rva    .LSEH_begin_AES_cbc_encrypt
        .rva    .LSEH_end_AES_cbc_encrypt
@@ -2788,11 +2797,11 @@ cbc_se_handler:
        .byte   9,0,0,0
        .rva    block_se_handler
        .rva    .Ldec_prologue,.Ldec_epilogue   # HandlerData[]
-.LSEH_info_AES_set_encrypt_key:
+.LSEH_info_private_AES_set_encrypt_key:
        .byte   9,0,0,0
        .rva    key_se_handler
        .rva    .Lenc_key_prologue,.Lenc_key_epilogue   # HandlerData[]
-.LSEH_info_AES_set_decrypt_key:
+.LSEH_info_private_AES_set_decrypt_key:
        .byte   9,0,0,0
        .rva    key_se_handler
        .rva    .Ldec_key_prologue,.Ldec_key_epilogue   # HandlerData[]
diff --git a/crypto/openssl/crypto/aes/asm/aesni-sha1-x86_64.pl b/crypto/openssl/crypto/aes/asm/aesni-sha1-x86_64.pl
new file mode 100644 (file)
index 0000000..c6f6b33
--- /dev/null
@@ -0,0 +1,1249 @@
+#!/usr/bin/env perl
+#
+# ====================================================================
+# Written by Andy Polyakov <appro@openssl.org> 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/.
+# ====================================================================
+#
+# June 2011
+#
+# This is AESNI-CBC+SHA1 "stitch" implementation. The idea, as spelled
+# in http://download.intel.com/design/intarch/papers/323686.pdf, is
+# that since AESNI-CBC encrypt exhibit *very* low instruction-level
+# parallelism, interleaving it with another algorithm would allow to
+# utilize processor resources better and achieve better performance.
+# SHA1 instruction sequences(*) are taken from sha1-x86_64.pl and
+# AESNI code is weaved into it. Below are performance numbers in
+# cycles per processed byte, less is better, for standalone AESNI-CBC
+# encrypt, sum of the latter and standalone SHA1, and "stitched"
+# subroutine:
+#
+#              AES-128-CBC     +SHA1           stitch      gain
+# Westmere     3.77[+5.6]      9.37            6.65        +41%
+# Sandy Bridge 5.05[+5.2(6.3)] 10.25(11.35)    6.16(7.08)  +67%(+60%)
+#
+#              AES-192-CBC
+# Westmere     4.51            10.11           6.97        +45%
+# Sandy Bridge 6.05            11.25(12.35)    6.34(7.27)  +77%(+70%)
+#
+#              AES-256-CBC
+# Westmere     5.25            10.85           7.25        +50%
+# Sandy Bridge 7.05            12.25(13.35)    7.06(7.70)  +74%(+73%)
+#
+# (*)  There are two code paths: SSSE3 and AVX. See sha1-568.pl for
+#      background information. Above numbers in parentheses are SSSE3
+#      results collected on AVX-capable CPU, i.e. apply on OSes that
+#      don't support AVX.
+#
+# Needless to mention that it makes no sense to implement "stitched"
+# *decrypt* subroutine. Because *both* AESNI-CBC decrypt and SHA1
+# fully utilize parallelism, so stitching would not give any gain
+# anyway. Well, there might be some, e.g. because of better cache
+# locality... For reference, here are performance results for
+# standalone AESNI-CBC decrypt:
+#
+#              AES-128-CBC     AES-192-CBC     AES-256-CBC
+# Westmere     1.31            1.55            1.80
+# Sandy Bridge 0.93            1.06            1.22
+
+$flavour = shift;
+$output  = shift;
+if ($flavour =~ /\./) { $output = $flavour; undef $flavour; }
+
+$win64=0; $win64=1 if ($flavour =~ /[nm]asm|mingw64/ || $output =~ /\.asm$/);
+
+$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
+( $xlate="${dir}x86_64-xlate.pl" and -f $xlate ) or
+( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or
+die "can't locate x86_64-xlate.pl";
+
+$avx=1 if (`$ENV{CC} -Wa,-v -c -o /dev/null -x assembler /dev/null 2>&1`
+               =~ /GNU assembler version ([2-9]\.[0-9]+)/ &&
+          $1>=2.19);
+$avx=1 if (!$avx && $win64 && ($flavour =~ /nasm/ || $ENV{ASM} =~ /nasm/) &&
+          `nasm -v 2>&1` =~ /NASM version ([2-9]\.[0-9]+)/ &&
+          $1>=2.09);
+$avx=1 if (!$avx && $win64 && ($flavour =~ /masm/ || $ENV{ASM} =~ /ml64/) &&
+          `ml64 2>&1` =~ /Version ([0-9]+)\./ &&
+          $1>=10);
+
+open STDOUT,"| $^X $xlate $flavour $output";
+
+# void aesni_cbc_sha1_enc(const void *inp,
+#                      void *out,
+#                      size_t length,
+#                      const AES_KEY *key,
+#                      unsigned char *iv,
+#                      SHA_CTX *ctx,
+#                      const void *in0);
+
+$code.=<<___;
+.text
+.extern        OPENSSL_ia32cap_P
+
+.globl aesni_cbc_sha1_enc
+.type  aesni_cbc_sha1_enc,\@abi-omnipotent
+.align 16
+aesni_cbc_sha1_enc:
+       # caller should check for SSSE3 and AES-NI bits
+       mov     OPENSSL_ia32cap_P+0(%rip),%r10d
+       mov     OPENSSL_ia32cap_P+4(%rip),%r11d
+___
+$code.=<<___ if ($avx);
+       and     \$`1<<28`,%r11d         # mask AVX bit
+       and     \$`1<<30`,%r10d         # mask "Intel CPU" bit
+       or      %r11d,%r10d
+       cmp     \$`1<<28|1<<30`,%r10d
+       je      aesni_cbc_sha1_enc_avx
+___
+$code.=<<___;
+       jmp     aesni_cbc_sha1_enc_ssse3
+       ret
+.size  aesni_cbc_sha1_enc,.-aesni_cbc_sha1_enc
+___
+
+my ($in0,$out,$len,$key,$ivp,$ctx,$inp)=("%rdi","%rsi","%rdx","%rcx","%r8","%r9","%r10");
+
+my $Xi=4;
+my @X=map("%xmm$_",(4..7,0..3));
+my @Tx=map("%xmm$_",(8..10));
+my @V=($A,$B,$C,$D,$E)=("%eax","%ebx","%ecx","%edx","%ebp");   # size optimization
+my @T=("%esi","%edi");
+my $j=0; my $jj=0; my $r=0; my $sn=0;
+my $K_XX_XX="%r11";
+my ($iv,$in,$rndkey0)=map("%xmm$_",(11..13));
+my @rndkey=("%xmm14","%xmm15");
+
+sub AUTOLOAD()         # thunk [simplified] 32-bit style perlasm
+{ my $opcode = $AUTOLOAD; $opcode =~ s/.*:://;
+  my $arg = pop;
+    $arg = "\$$arg" if ($arg*1 eq $arg);
+    $code .= "\t$opcode\t".join(',',$arg,reverse @_)."\n";
+}
+
+my $_rol=sub { &rol(@_) };
+my $_ror=sub { &ror(@_) };
+
+$code.=<<___;
+.type  aesni_cbc_sha1_enc_ssse3,\@function,6
+.align 16
+aesni_cbc_sha1_enc_ssse3:
+       mov     `($win64?56:8)`(%rsp),$inp      # load 7th argument
+       #shr    \$6,$len                        # debugging artefact
+       #jz     .Lepilogue_ssse3                # debugging artefact
+       push    %rbx
+       push    %rbp
+       push    %r12
+       push    %r13
+       push    %r14
+       push    %r15
+       lea     `-104-($win64?10*16:0)`(%rsp),%rsp
+       #mov    $in0,$inp                       # debugging artefact
+       #lea    64(%rsp),$ctx                   # debugging artefact
+___
+$code.=<<___ if ($win64);
+       movaps  %xmm6,96+0(%rsp)
+       movaps  %xmm7,96+16(%rsp)
+       movaps  %xmm8,96+32(%rsp)
+       movaps  %xmm9,96+48(%rsp)
+       movaps  %xmm10,96+64(%rsp)
+       movaps  %xmm11,96+80(%rsp)
+       movaps  %xmm12,96+96(%rsp)
+       movaps  %xmm13,96+112(%rsp)
+       movaps  %xmm14,96+128(%rsp)
+       movaps  %xmm15,96+144(%rsp)
+.Lprologue_ssse3:
+___
+$code.=<<___;
+       mov     $in0,%r12                       # reassign arguments
+       mov     $out,%r13
+       mov     $len,%r14
+       mov     $key,%r15
+       movdqu  ($ivp),$iv                      # load IV
+       mov     $ivp,88(%rsp)                   # save $ivp
+___
+my ($in0,$out,$len,$key)=map("%r$_",(12..15)); # reassign arguments
+my $rounds="${ivp}d";
+$code.=<<___;
+       shl     \$6,$len
+       sub     $in0,$out
+       mov     240($key),$rounds
+       add     $inp,$len               # end of input
+
+       lea     K_XX_XX(%rip),$K_XX_XX
+       mov     0($ctx),$A              # load context
+       mov     4($ctx),$B
+       mov     8($ctx),$C
+       mov     12($ctx),$D
+       mov     $B,@T[0]                # magic seed
+       mov     16($ctx),$E
+
+       movdqa  64($K_XX_XX),@X[2]      # pbswap mask
+       movdqa  0($K_XX_XX),@Tx[1]      # K_00_19
+       movdqu  0($inp),@X[-4&7]        # load input to %xmm[0-3]
+       movdqu  16($inp),@X[-3&7]
+       movdqu  32($inp),@X[-2&7]
+       movdqu  48($inp),@X[-1&7]
+       pshufb  @X[2],@X[-4&7]          # byte swap
+       add     \$64,$inp
+       pshufb  @X[2],@X[-3&7]
+       pshufb  @X[2],@X[-2&7]
+       pshufb  @X[2],@X[-1&7]
+       paddd   @Tx[1],@X[-4&7]         # add K_00_19
+       paddd   @Tx[1],@X[-3&7]
+       paddd   @Tx[1],@X[-2&7]
+       movdqa  @X[-4&7],0(%rsp)        # X[]+K xfer to IALU
+       psubd   @Tx[1],@X[-4&7]         # restore X[]
+       movdqa  @X[-3&7],16(%rsp)
+       psubd   @Tx[1],@X[-3&7]
+       movdqa  @X[-2&7],32(%rsp)
+       psubd   @Tx[1],@X[-2&7]
+       movups  ($key),$rndkey0         # $key[0]
+       movups  16($key),$rndkey[0]     # forward reference
+       jmp     .Loop_ssse3
+___
+
+my $aesenc=sub {
+  use integer;
+  my ($n,$k)=($r/10,$r%10);
+    if ($k==0) {
+      $code.=<<___;
+       movups          `16*$n`($in0),$in               # load input
+       xorps           $rndkey0,$in
+___
+      $code.=<<___ if ($n);
+       movups          $iv,`16*($n-1)`($out,$in0)      # write output
+___
+      $code.=<<___;
+       xorps           $in,$iv
+       aesenc          $rndkey[0],$iv
+       movups          `32+16*$k`($key),$rndkey[1]
+___
+    } elsif ($k==9) {
+      $sn++;
+      $code.=<<___;
+       cmp             \$11,$rounds
+       jb              .Laesenclast$sn
+       movups          `32+16*($k+0)`($key),$rndkey[1]
+       aesenc          $rndkey[0],$iv
+       movups          `32+16*($k+1)`($key),$rndkey[0]
+       aesenc          $rndkey[1],$iv
+       je              .Laesenclast$sn
+       movups          `32+16*($k+2)`($key),$rndkey[1]
+       aesenc          $rndkey[0],$iv
+       movups          `32+16*($k+3)`($key),$rndkey[0]
+       aesenc          $rndkey[1],$iv
+.Laesenclast$sn:
+       aesenclast      $rndkey[0],$iv
+       movups          16($key),$rndkey[1]             # forward reference
+___
+    } else {
+      $code.=<<___;
+       aesenc          $rndkey[0],$iv
+       movups          `32+16*$k`($key),$rndkey[1]
+___
+    }
+    $r++;      unshift(@rndkey,pop(@rndkey));
+};
+
+sub Xupdate_ssse3_16_31()              # recall that $Xi starts wtih 4
+{ use integer;
+  my $body = shift;
+  my @insns = (&$body,&$body,&$body,&$body);   # 40 instructions
+  my ($a,$b,$c,$d,$e);
+
+       &movdqa (@X[0],@X[-3&7]);
+        eval(shift(@insns));
+        eval(shift(@insns));
+       &movdqa (@Tx[0],@X[-1&7]);
+       &palignr(@X[0],@X[-4&7],8);     # compose "X[-14]" in "X[0]"
+        eval(shift(@insns));
+        eval(shift(@insns));
+
+         &paddd        (@Tx[1],@X[-1&7]);
+        eval(shift(@insns));
+        eval(shift(@insns));
+       &psrldq (@Tx[0],4);             # "X[-3]", 3 dwords
+        eval(shift(@insns));
+        eval(shift(@insns));
+       &pxor   (@X[0],@X[-4&7]);       # "X[0]"^="X[-16]"
+        eval(shift(@insns));
+        eval(shift(@insns));
+
+       &pxor   (@Tx[0],@X[-2&7]);      # "X[-3]"^"X[-8]"
+        eval(shift(@insns));
+        eval(shift(@insns));
+        eval(shift(@insns));
+        eval(shift(@insns));
+
+       &pxor   (@X[0],@Tx[0]);         # "X[0]"^="X[-3]"^"X[-8]"
+        eval(shift(@insns));
+        eval(shift(@insns));
+         &movdqa       (eval(16*(($Xi-1)&3))."(%rsp)",@Tx[1]); # X[]+K xfer to IALU
+        eval(shift(@insns));
+        eval(shift(@insns));
+
+       &movdqa (@Tx[2],@X[0]);
+       &movdqa (@Tx[0],@X[0]);
+        eval(shift(@insns));
+        eval(shift(@insns));
+        eval(shift(@insns));
+        eval(shift(@insns));
+
+       &pslldq (@Tx[2],12);            # "X[0]"<<96, extract one dword
+       &paddd  (@X[0],@X[0]);
+        eval(shift(@insns));
+        eval(shift(@insns));
+        eval(shift(@insns));
+        eval(shift(@insns));
+
+       &psrld  (@Tx[0],31);
+        eval(shift(@insns));
+        eval(shift(@insns));
+       &movdqa (@Tx[1],@Tx[2]);
+        eval(shift(@insns));
+        eval(shift(@insns));
+
+       &psrld  (@Tx[2],30);
+       &por    (@X[0],@Tx[0]);         # "X[0]"<<<=1
+        eval(shift(@insns));
+        eval(shift(@insns));
+        eval(shift(@insns));
+        eval(shift(@insns));
+
+       &pslld  (@Tx[1],2);
+       &pxor   (@X[0],@Tx[2]);
+        eval(shift(@insns));
+        eval(shift(@insns));
+         &movdqa       (@Tx[2],eval(16*(($Xi)/5))."($K_XX_XX)");       # K_XX_XX
+        eval(shift(@insns));
+        eval(shift(@insns));
+
+       &pxor   (@X[0],@Tx[1]);         # "X[0]"^=("X[0]">>96)<<<2
+
+        foreach (@insns) { eval; }     # remaining instructions [if any]
+
+  $Xi++;       push(@X,shift(@X));     # "rotate" X[]
+               push(@Tx,shift(@Tx));
+}
+
+sub Xupdate_ssse3_32_79()
+{ use integer;
+  my $body = shift;
+  my @insns = (&$body,&$body,&$body,&$body);   # 32 to 48 instructions
+  my ($a,$b,$c,$d,$e);
+
+       &movdqa (@Tx[0],@X[-1&7])       if ($Xi==8);
+        eval(shift(@insns));           # body_20_39
+       &pxor   (@X[0],@X[-4&7]);       # "X[0]"="X[-32]"^"X[-16]"
+       &palignr(@Tx[0],@X[-2&7],8);    # compose "X[-6]"
+        eval(shift(@insns));
+        eval(shift(@insns));
+        eval(shift(@insns));           # rol
+
+       &pxor   (@X[0],@X[-7&7]);       # "X[0]"^="X[-28]"
+        eval(shift(@insns));
+        eval(shift(@insns))    if (@insns[0] !~ /&ro[rl]/);
+       if ($Xi%5) {
+         &movdqa       (@Tx[2],@Tx[1]);# "perpetuate" K_XX_XX...
+       } else {                        # ... or load next one
+         &movdqa       (@Tx[2],eval(16*($Xi/5))."($K_XX_XX)");
+       }
+         &paddd        (@Tx[1],@X[-1&7]);
+        eval(shift(@insns));           # ror
+        eval(shift(@insns));
+
+       &pxor   (@X[0],@Tx[0]);         # "X[0]"^="X[-6]"
+        eval(shift(@insns));           # body_20_39
+        eval(shift(@insns));
+        eval(shift(@insns));
+        eval(shift(@insns));           # rol
+
+       &movdqa (@Tx[0],@X[0]);
+         &movdqa       (eval(16*(($Xi-1)&3))."(%rsp)",@Tx[1]); # X[]+K xfer to IALU
+        eval(shift(@insns));
+        eval(shift(@insns));
+        eval(shift(@insns));           # ror
+        eval(shift(@insns));
+
+       &pslld  (@X[0],2);
+        eval(shift(@insns));           # body_20_39
+        eval(shift(@insns));
+       &psrld  (@Tx[0],30);
+        eval(shift(@insns));
+        eval(shift(@insns));           # rol
+        eval(shift(@insns));
+        eval(shift(@insns));
+        eval(shift(@insns));           # ror
+        eval(shift(@insns));
+
+       &por    (@X[0],@Tx[0]);         # "X[0]"<<<=2
+        eval(shift(@insns));           # body_20_39
+        eval(shift(@insns));
+         &movdqa       (@Tx[1],@X[0])  if ($Xi<19);
+        eval(shift(@insns));
+        eval(shift(@insns));           # rol
+        eval(shift(@insns));
+        eval(shift(@insns));
+        eval(shift(@insns));           # rol
+        eval(shift(@insns));
+
+        foreach (@insns) { eval; }     # remaining instructions
+
+  $Xi++;       push(@X,shift(@X));     # "rotate" X[]
+               push(@Tx,shift(@Tx));
+}
+
+sub Xuplast_ssse3_80()
+{ use integer;
+  my $body = shift;
+  my @insns = (&$body,&$body,&$body,&$body);   # 32 instructions
+  my ($a,$b,$c,$d,$e);
+
+        eval(shift(@insns));
+         &paddd        (@Tx[1],@X[-1&7]);
+        eval(shift(@insns));
+        eval(shift(@insns));
+        eval(shift(@insns));
+        eval(shift(@insns));
+
+         &movdqa       (eval(16*(($Xi-1)&3))."(%rsp)",@Tx[1]); # X[]+K xfer IALU
+
+        foreach (@insns) { eval; }             # remaining instructions
+
+       &cmp    ($inp,$len);
+       &je     (".Ldone_ssse3");
+
+       unshift(@Tx,pop(@Tx));
+
+       &movdqa (@X[2],"64($K_XX_XX)");         # pbswap mask
+       &movdqa (@Tx[1],"0($K_XX_XX)");         # K_00_19
+       &movdqu (@X[-4&7],"0($inp)");           # load input
+       &movdqu (@X[-3&7],"16($inp)");
+       &movdqu (@X[-2&7],"32($inp)");
+       &movdqu (@X[-1&7],"48($inp)");
+       &pshufb (@X[-4&7],@X[2]);               # byte swap
+       &add    ($inp,64);
+
+  $Xi=0;
+}
+
+sub Xloop_ssse3()
+{ use integer;
+  my $body = shift;
+  my @insns = (&$body,&$body,&$body,&$body);   # 32 instructions
+  my ($a,$b,$c,$d,$e);
+
+        eval(shift(@insns));
+        eval(shift(@insns));
+       &pshufb (@X[($Xi-3)&7],@X[2]);
+        eval(shift(@insns));
+        eval(shift(@insns));
+       &paddd  (@X[($Xi-4)&7],@Tx[1]);
+        eval(shift(@insns));
+        eval(shift(@insns));
+        eval(shift(@insns));
+        eval(shift(@insns));
+       &movdqa (eval(16*$Xi)."(%rsp)",@X[($Xi-4)&7]);  # X[]+K xfer to IALU
+        eval(shift(@insns));
+        eval(shift(@insns));
+       &psubd  (@X[($Xi-4)&7],@Tx[1]);
+
+       foreach (@insns) { eval; }
+  $Xi++;
+}
+
+sub Xtail_ssse3()
+{ use integer;
+  my $body = shift;
+  my @insns = (&$body,&$body,&$body,&$body);   # 32 instructions
+  my ($a,$b,$c,$d,$e);
+
+       foreach (@insns) { eval; }
+}
+
+sub body_00_19 () {
+  use integer;
+  my ($k,$n);
+  my @r=(
+       '($a,$b,$c,$d,$e)=@V;'.
+       '&add   ($e,eval(4*($j&15))."(%rsp)");',        # X[]+K xfer
+       '&xor   ($c,$d);',
+       '&mov   (@T[1],$a);',   # $b in next round
+       '&$_rol ($a,5);',
+       '&and   (@T[0],$c);',   # ($b&($c^$d))
+       '&xor   ($c,$d);',      # restore $c
+       '&xor   (@T[0],$d);',
+       '&add   ($e,$a);',
+       '&$_ror ($b,$j?7:2);',  # $b>>>2
+       '&add   ($e,@T[0]);'    .'$j++; unshift(@V,pop(@V)); unshift(@T,pop(@T));'
+       );
+       $n = scalar(@r);
+       $k = (($jj+1)*12/20)*20*$n/12;  # 12 aesencs per these 20 rounds
+       @r[$k%$n].='&$aesenc();'        if ($jj==$k/$n);
+       $jj++;
+    return @r;
+}
+
+sub body_20_39 () {
+  use integer;
+  my ($k,$n);
+  my @r=(
+       '($a,$b,$c,$d,$e)=@V;'.
+       '&add   ($e,eval(4*($j++&15))."(%rsp)");',      # X[]+K xfer
+       '&xor   (@T[0],$d);',   # ($b^$d)
+       '&mov   (@T[1],$a);',   # $b in next round
+       '&$_rol ($a,5);',
+       '&xor   (@T[0],$c);',   # ($b^$d^$c)
+       '&add   ($e,$a);',
+       '&$_ror ($b,7);',       # $b>>>2
+       '&add   ($e,@T[0]);'    .'unshift(@V,pop(@V)); unshift(@T,pop(@T));'
+       );
+       $n = scalar(@r);
+       $k = (($jj+1)*8/20)*20*$n/8;    # 8 aesencs per these 20 rounds
+       @r[$k%$n].='&$aesenc();'        if ($jj==$k/$n);
+       $jj++;
+    return @r;
+}
+
+sub body_40_59 () {
+  use integer;
+  my ($k,$n);
+  my @r=(
+       '($a,$b,$c,$d,$e)=@V;'.
+       '&mov   (@T[1],$c);',
+       '&xor   ($c,$d);',
+       '&add   ($e,eval(4*($j++&15))."(%rsp)");',      # X[]+K xfer
+       '&and   (@T[1],$d);',
+       '&and   (@T[0],$c);',   # ($b&($c^$d))
+       '&$_ror ($b,7);',       # $b>>>2
+       '&add   ($e,@T[1]);',
+       '&mov   (@T[1],$a);',   # $b in next round
+       '&$_rol ($a,5);',
+       '&add   ($e,@T[0]);',
+       '&xor   ($c,$d);',      # restore $c
+       '&add   ($e,$a);'       .'unshift(@V,pop(@V)); unshift(@T,pop(@T));'
+       );
+       $n = scalar(@r);
+       $k=(($jj+1)*12/20)*20*$n/12;    # 12 aesencs per these 20 rounds
+       @r[$k%$n].='&$aesenc();'        if ($jj==$k/$n);
+       $jj++;
+    return @r;
+}
+$code.=<<___;
+.align 16
+.Loop_ssse3:
+___
+       &Xupdate_ssse3_16_31(\&body_00_19);
+       &Xupdate_ssse3_16_31(\&body_00_19);
+       &Xupdate_ssse3_16_31(\&body_00_19);
+       &Xupdate_ssse3_16_31(\&body_00_19);
+       &Xupdate_ssse3_32_79(\&body_00_19);
+       &Xupdate_ssse3_32_79(\&body_20_39);
+       &Xupdate_ssse3_32_79(\&body_20_39);
+       &Xupdate_ssse3_32_79(\&body_20_39);
+       &Xupdate_ssse3_32_79(\&body_20_39);
+       &Xupdate_ssse3_32_79(\&body_20_39);
+       &Xupdate_ssse3_32_79(\&body_40_59);
+       &Xupdate_ssse3_32_79(\&body_40_59);
+       &Xupdate_ssse3_32_79(\&body_40_59);
+       &Xupdate_ssse3_32_79(\&body_40_59);
+       &Xupdate_ssse3_32_79(\&body_40_59);
+       &Xupdate_ssse3_32_79(\&body_20_39);
+       &Xuplast_ssse3_80(\&body_20_39);        # can jump to "done"
+
+                               $saved_j=$j; @saved_V=@V;
+                               $saved_r=$r; @saved_rndkey=@rndkey;
+
+       &Xloop_ssse3(\&body_20_39);
+       &Xloop_ssse3(\&body_20_39);
+       &Xloop_ssse3(\&body_20_39);
+
+$code.=<<___;
+       movups  $iv,48($out,$in0)               # write output
+       lea     64($in0),$in0
+
+       add     0($ctx),$A                      # update context
+       add     4($ctx),@T[0]
+       add     8($ctx),$C
+       add     12($ctx),$D
+       mov     $A,0($ctx)
+       add     16($ctx),$E
+       mov     @T[0],4($ctx)
+       mov     @T[0],$B                        # magic seed
+       mov     $C,8($ctx)
+       mov     $D,12($ctx)
+       mov     $E,16($ctx)
+       jmp     .Loop_ssse3
+
+.align 16
+.Ldone_ssse3:
+___
+                               $jj=$j=$saved_j; @V=@saved_V;
+                               $r=$saved_r;     @rndkey=@saved_rndkey;
+
+       &Xtail_ssse3(\&body_20_39);
+       &Xtail_ssse3(\&body_20_39);
+       &Xtail_ssse3(\&body_20_39);
+
+$code.=<<___;
+       movups  $iv,48($out,$in0)               # write output
+       mov     88(%rsp),$ivp                   # restore $ivp
+
+       add     0($ctx),$A                      # update context
+       add     4($ctx),@T[0]
+       add     8($ctx),$C
+       mov     $A,0($ctx)
+       add     12($ctx),$D
+       mov     @T[0],4($ctx)
+       add     16($ctx),$E
+       mov     $C,8($ctx)
+       mov     $D,12($ctx)
+       mov     $E,16($ctx)
+       movups  $iv,($ivp)                      # write IV
+___
+$code.=<<___ if ($win64);
+       movaps  96+0(%rsp),%xmm6
+       movaps  96+16(%rsp),%xmm7
+       movaps  96+32(%rsp),%xmm8
+       movaps  96+48(%rsp),%xmm9
+       movaps  96+64(%rsp),%xmm10
+       movaps  96+80(%rsp),%xmm11
+       movaps  96+96(%rsp),%xmm12
+       movaps  96+112(%rsp),%xmm13
+       movaps  96+128(%rsp),%xmm14
+       movaps  96+144(%rsp),%xmm15
+___
+$code.=<<___;
+       lea     `104+($win64?10*16:0)`(%rsp),%rsi
+       mov     0(%rsi),%r15
+       mov     8(%rsi),%r14
+       mov     16(%rsi),%r13
+       mov     24(%rsi),%r12
+       mov     32(%rsi),%rbp
+       mov     40(%rsi),%rbx
+       lea     48(%rsi),%rsp
+.Lepilogue_ssse3:
+       ret
+.size  aesni_cbc_sha1_enc_ssse3,.-aesni_cbc_sha1_enc_ssse3
+___
+
+$j=$jj=$r=$sn=0;
+
+if ($avx) {
+my ($in0,$out,$len,$key,$ivp,$ctx,$inp)=("%rdi","%rsi","%rdx","%rcx","%r8","%r9","%r10");
+
+my $Xi=4;
+my @X=map("%xmm$_",(4..7,0..3));
+my @Tx=map("%xmm$_",(8..10));
+my @V=($A,$B,$C,$D,$E)=("%eax","%ebx","%ecx","%edx","%ebp");   # size optimization
+my @T=("%esi","%edi");
+
+my $_rol=sub { &shld(@_[0],@_) };
+my $_ror=sub { &shrd(@_[0],@_) };
+
+$code.=<<___;
+.type  aesni_cbc_sha1_enc_avx,\@function,6
+.align 16
+aesni_cbc_sha1_enc_avx:
+       mov     `($win64?56:8)`(%rsp),$inp      # load 7th argument
+       #shr    \$6,$len                        # debugging artefact
+       #jz     .Lepilogue_avx                  # debugging artefact
+       push    %rbx
+       push    %rbp
+       push    %r12
+       push    %r13
+       push    %r14
+       push    %r15
+       lea     `-104-($win64?10*16:0)`(%rsp),%rsp
+       #mov    $in0,$inp                       # debugging artefact
+       #lea    64(%rsp),$ctx                   # debugging artefact
+___
+$code.=<<___ if ($win64);
+       movaps  %xmm6,96+0(%rsp)
+       movaps  %xmm7,96+16(%rsp)
+       movaps  %xmm8,96+32(%rsp)
+       movaps  %xmm9,96+48(%rsp)
+       movaps  %xmm10,96+64(%rsp)
+       movaps  %xmm11,96+80(%rsp)
+       movaps  %xmm12,96+96(%rsp)
+       movaps  %xmm13,96+112(%rsp)
+       movaps  %xmm14,96+128(%rsp)
+       movaps  %xmm15,96+144(%rsp)
+.Lprologue_avx:
+___
+$code.=<<___;
+       vzeroall
+       mov     $in0,%r12                       # reassign arguments
+       mov     $out,%r13
+       mov     $len,%r14
+       mov     $key,%r15
+       vmovdqu ($ivp),$iv                      # load IV
+       mov     $ivp,88(%rsp)                   # save $ivp
+___
+my ($in0,$out,$len,$key)=map("%r$_",(12..15)); # reassign arguments
+my $rounds="${ivp}d";
+$code.=<<___;
+       shl     \$6,$len
+       sub     $in0,$out
+       mov     240($key),$rounds
+       add     \$112,$key              # size optimization
+       add     $inp,$len               # end of input
+
+       lea     K_XX_XX(%rip),$K_XX_XX
+       mov     0($ctx),$A              # load context
+       mov     4($ctx),$B
+       mov     8($ctx),$C
+       mov     12($ctx),$D
+       mov     $B,@T[0]                # magic seed
+       mov     16($ctx),$E
+
+       vmovdqa 64($K_XX_XX),@X[2]      # pbswap mask
+       vmovdqa 0($K_XX_XX),@Tx[1]      # K_00_19
+       vmovdqu 0($inp),@X[-4&7]        # load input to %xmm[0-3]
+       vmovdqu 16($inp),@X[-3&7]
+       vmovdqu 32($inp),@X[-2&7]
+       vmovdqu 48($inp),@X[-1&7]
+       vpshufb @X[2],@X[-4&7],@X[-4&7] # byte swap
+       add     \$64,$inp
+       vpshufb @X[2],@X[-3&7],@X[-3&7]
+       vpshufb @X[2],@X[-2&7],@X[-2&7]
+       vpshufb @X[2],@X[-1&7],@X[-1&7]
+       vpaddd  @Tx[1],@X[-4&7],@X[0]   # add K_00_19
+       vpaddd  @Tx[1],@X[-3&7],@X[1]
+       vpaddd  @Tx[1],@X[-2&7],@X[2]
+       vmovdqa @X[0],0(%rsp)           # X[]+K xfer to IALU
+       vmovdqa @X[1],16(%rsp)
+       vmovdqa @X[2],32(%rsp)
+       vmovups -112($key),$rndkey0     # $key[0]
+       vmovups 16-112($key),$rndkey[0] # forward reference
+       jmp     .Loop_avx
+___
+
+my $aesenc=sub {
+  use integer;
+  my ($n,$k)=($r/10,$r%10);
+    if ($k==0) {
+      $code.=<<___;
+       vmovups         `16*$n`($in0),$in               # load input
+       vxorps          $rndkey0,$in,$in
+___
+      $code.=<<___ if ($n);
+       vmovups         $iv,`16*($n-1)`($out,$in0)      # write output
+___
+      $code.=<<___;
+       vxorps          $in,$iv,$iv
+       vaesenc         $rndkey[0],$iv,$iv
+       vmovups         `32+16*$k-112`($key),$rndkey[1]
+___
+    } elsif ($k==9) {
+      $sn++;
+      $code.=<<___;
+       cmp             \$11,$rounds
+       jb              .Lvaesenclast$sn
+       vaesenc         $rndkey[0],$iv,$iv
+       vmovups         `32+16*($k+0)-112`($key),$rndkey[1]
+       vaesenc         $rndkey[1],$iv,$iv
+       vmovups         `32+16*($k+1)-112`($key),$rndkey[0]
+       je              .Lvaesenclast$sn
+       vaesenc         $rndkey[0],$iv,$iv
+       vmovups         `32+16*($k+2)-112`($key),$rndkey[1]
+       vaesenc         $rndkey[1],$iv,$iv
+       vmovups         `32+16*($k+3)-112`($key),$rndkey[0]
+.Lvaesenclast$sn:
+       vaesenclast     $rndkey[0],$iv,$iv
+       vmovups         16-112($key),$rndkey[1]         # forward reference
+___
+    } else {
+      $code.=<<___;
+       vaesenc         $rndkey[0],$iv,$iv
+       vmovups         `32+16*$k-112`($key),$rndkey[1]
+___
+    }
+    $r++;      unshift(@rndkey,pop(@rndkey));
+};
+
+sub Xupdate_avx_16_31()                # recall that $Xi starts wtih 4
+{ use integer;
+  my $body = shift;
+  my @insns = (&$body,&$body,&$body,&$body);   # 40 instructions
+  my ($a,$b,$c,$d,$e);
+
+        eval(shift(@insns));
+        eval(shift(@insns));
+       &vpalignr(@X[0],@X[-3&7],@X[-4&7],8);   # compose "X[-14]" in "X[0]"
+        eval(shift(@insns));
+        eval(shift(@insns));
+
+         &vpaddd       (@Tx[1],@Tx[1],@X[-1&7]);
+        eval(shift(@insns));
+        eval(shift(@insns));
+       &vpsrldq(@Tx[0],@X[-1&7],4);    # "X[-3]", 3 dwords
+        eval(shift(@insns));
+        eval(shift(@insns));
+       &vpxor  (@X[0],@X[0],@X[-4&7]);         # "X[0]"^="X[-16]"
+        eval(shift(@insns));
+        eval(shift(@insns));
+
+       &vpxor  (@Tx[0],@Tx[0],@X[-2&7]);       # "X[-3]"^"X[-8]"
+        eval(shift(@insns));
+        eval(shift(@insns));
+        eval(shift(@insns));
+        eval(shift(@insns));
+
+       &vpxor  (@X[0],@X[0],@Tx[0]);           # "X[0]"^="X[-3]"^"X[-8]"
+        eval(shift(@insns));
+        eval(shift(@insns));
+         &vmovdqa      (eval(16*(($Xi-1)&3))."(%rsp)",@Tx[1]); # X[]+K xfer to IALU
+        eval(shift(@insns));
+        eval(shift(@insns));
+
+       &vpsrld (@Tx[0],@X[0],31);
+        eval(shift(@insns));
+        eval(shift(@insns));
+        eval(shift(@insns));
+        eval(shift(@insns));
+
+       &vpslldq(@Tx[2],@X[0],12);              # "X[0]"<<96, extract one dword
+       &vpaddd (@X[0],@X[0],@X[0]);
+        eval(shift(@insns));
+        eval(shift(@insns));
+        eval(shift(@insns));
+        eval(shift(@insns));
+
+       &vpsrld (@Tx[1],@Tx[2],30);
+       &vpor   (@X[0],@X[0],@Tx[0]);           # "X[0]"<<<=1
+        eval(shift(@insns));
+        eval(shift(@insns));
+        eval(shift(@insns));
+        eval(shift(@insns));
+
+       &vpslld (@Tx[2],@Tx[2],2);
+       &vpxor  (@X[0],@X[0],@Tx[1]);
+        eval(shift(@insns));
+        eval(shift(@insns));
+        eval(shift(@insns));
+        eval(shift(@insns));
+
+       &vpxor  (@X[0],@X[0],@Tx[2]);           # "X[0]"^=("X[0]">>96)<<<2
+        eval(shift(@insns));
+        eval(shift(@insns));
+         &vmovdqa      (@Tx[2],eval(16*(($Xi)/5))."($K_XX_XX)");       # K_XX_XX
+        eval(shift(@insns));
+        eval(shift(@insns));
+
+
+        foreach (@insns) { eval; }     # remaining instructions [if any]
+
+  $Xi++;       push(@X,shift(@X));     # "rotate" X[]
+               push(@Tx,shift(@Tx));
+}
+
+sub Xupdate_avx_32_79()
+{ use integer;
+  my $body = shift;
+  my @insns = (&$body,&$body,&$body,&$body);   # 32 to 48 instructions
+  my ($a,$b,$c,$d,$e);
+
+       &vpalignr(@Tx[0],@X[-1&7],@X[-2&7],8);  # compose "X[-6]"
+       &vpxor  (@X[0],@X[0],@X[-4&7]);         # "X[0]"="X[-32]"^"X[-16]"
+        eval(shift(@insns));           # body_20_39
+        eval(shift(@insns));
+        eval(shift(@insns));
+        eval(shift(@insns));           # rol
+
+       &vpxor  (@X[0],@X[0],@X[-7&7]);         # "X[0]"^="X[-28]"
+        eval(shift(@insns));
+        eval(shift(@insns))    if (@insns[0] !~ /&ro[rl]/);
+       if ($Xi%5) {
+         &vmovdqa      (@Tx[2],@Tx[1]);# "perpetuate" K_XX_XX...
+       } else {                        # ... or load next one
+         &vmovdqa      (@Tx[2],eval(16*($Xi/5))."($K_XX_XX)");
+       }
+         &vpaddd       (@Tx[1],@Tx[1],@X[-1&7]);
+        eval(shift(@insns));           # ror
+        eval(shift(@insns));
+
+       &vpxor  (@X[0],@X[0],@Tx[0]);           # "X[0]"^="X[-6]"
+        eval(shift(@insns));           # body_20_39
+        eval(shift(@insns));
+        eval(shift(@insns));
+        eval(shift(@insns));           # rol
+
+       &vpsrld (@Tx[0],@X[0],30);
+         &vmovdqa      (eval(16*(($Xi-1)&3))."(%rsp)",@Tx[1]); # X[]+K xfer to IALU
+        eval(shift(@insns));
+        eval(shift(@insns));
+        eval(shift(@insns));           # ror
+        eval(shift(@insns));
+
+       &vpslld (@X[0],@X[0],2);
+        eval(shift(@insns));           # body_20_39
+        eval(shift(@insns));
+        eval(shift(@insns));
+        eval(shift(@insns));           # rol
+        eval(shift(@insns));
+        eval(shift(@insns));
+        eval(shift(@insns));           # ror
+        eval(shift(@insns));
+
+       &vpor   (@X[0],@X[0],@Tx[0]);           # "X[0]"<<<=2
+        eval(shift(@insns));           # body_20_39
+        eval(shift(@insns));
+         &vmovdqa      (@Tx[1],@X[0])  if ($Xi<19);
+        eval(shift(@insns));
+        eval(shift(@insns));           # rol
+        eval(shift(@insns));
+        eval(shift(@insns));
+        eval(shift(@insns));           # rol
+        eval(shift(@insns));
+
+        foreach (@insns) { eval; }     # remaining instructions
+
+  $Xi++;       push(@X,shift(@X));     # "rotate" X[]
+               push(@Tx,shift(@Tx));
+}
+
+sub Xuplast_avx_80()
+{ use integer;
+  my $body = shift;
+  my @insns = (&$body,&$body,&$body,&$body);   # 32 instructions
+  my ($a,$b,$c,$d,$e);
+
+        eval(shift(@insns));
+         &vpaddd       (@Tx[1],@Tx[1],@X[-1&7]);
+        eval(shift(@insns));
+        eval(shift(@insns));
+        eval(shift(@insns));
+        eval(shift(@insns));
+
+         &movdqa       (eval(16*(($Xi-1)&3))."(%rsp)",@Tx[1]); # X[]+K xfer IALU
+
+        foreach (@insns) { eval; }             # remaining instructions
+
+       &cmp    ($inp,$len);
+       &je     (".Ldone_avx");
+
+       unshift(@Tx,pop(@Tx));
+
+       &vmovdqa(@X[2],"64($K_XX_XX)");         # pbswap mask
+       &vmovdqa(@Tx[1],"0($K_XX_XX)");         # K_00_19
+       &vmovdqu(@X[-4&7],"0($inp)");           # load input
+       &vmovdqu(@X[-3&7],"16($inp)");
+       &vmovdqu(@X[-2&7],"32($inp)");
+       &vmovdqu(@X[-1&7],"48($inp)");
+       &vpshufb(@X[-4&7],@X[-4&7],@X[2]);      # byte swap
+       &add    ($inp,64);
+
+  $Xi=0;
+}
+
+sub Xloop_avx()
+{ use integer;
+  my $body = shift;
+  my @insns = (&$body,&$body,&$body,&$body);   # 32 instructions
+  my ($a,$b,$c,$d,$e);
+
+        eval(shift(@insns));
+        eval(shift(@insns));
+       &vpshufb(@X[($Xi-3)&7],@X[($Xi-3)&7],@X[2]);
+        eval(shift(@insns));
+        eval(shift(@insns));
+       &vpaddd (@X[$Xi&7],@X[($Xi-4)&7],@Tx[1]);
+        eval(shift(@insns));
+        eval(shift(@insns));
+        eval(shift(@insns));
+        eval(shift(@insns));
+       &vmovdqa(eval(16*$Xi)."(%rsp)",@X[$Xi&7]);      # X[]+K xfer to IALU
+        eval(shift(@insns));
+        eval(shift(@insns));
+
+       foreach (@insns) { eval; }
+  $Xi++;
+}
+
+sub Xtail_avx()
+{ use integer;
+  my $body = shift;
+  my @insns = (&$body,&$body,&$body,&$body);   # 32 instructions
+  my ($a,$b,$c,$d,$e);
+
+       foreach (@insns) { eval; }
+}
+
+$code.=<<___;
+.align 16
+.Loop_avx:
+___
+       &Xupdate_avx_16_31(\&body_00_19);
+       &Xupdate_avx_16_31(\&body_00_19);
+       &Xupdate_avx_16_31(\&body_00_19);
+       &Xupdate_avx_16_31(\&body_00_19);
+       &Xupdate_avx_32_79(\&body_00_19);
+       &Xupdate_avx_32_79(\&body_20_39);
+       &Xupdate_avx_32_79(\&body_20_39);
+       &Xupdate_avx_32_79(\&body_20_39);
+       &Xupdate_avx_32_79(\&body_20_39);
+       &Xupdate_avx_32_79(\&body_20_39);
+       &Xupdate_avx_32_79(\&body_40_59);
+       &Xupdate_avx_32_79(\&body_40_59);
+       &Xupdate_avx_32_79(\&body_40_59);
+       &Xupdate_avx_32_79(\&body_40_59);
+       &Xupdate_avx_32_79(\&body_40_59);
+       &Xupdate_avx_32_79(\&body_20_39);
+       &Xuplast_avx_80(\&body_20_39);  # can jump to "done"
+
+                               $saved_j=$j; @saved_V=@V;
+                               $saved_r=$r; @saved_rndkey=@rndkey;
+
+       &Xloop_avx(\&body_20_39);
+       &Xloop_avx(\&body_20_39);
+       &Xloop_avx(\&body_20_39);
+
+$code.=<<___;
+       vmovups $iv,48($out,$in0)               # write output
+       lea     64($in0),$in0
+
+       add     0($ctx),$A                      # update context
+       add     4($ctx),@T[0]
+       add     8($ctx),$C
+       add     12($ctx),$D
+       mov     $A,0($ctx)
+       add     16($ctx),$E
+       mov     @T[0],4($ctx)
+       mov     @T[0],$B                        # magic seed
+       mov     $C,8($ctx)
+       mov     $D,12($ctx)
+       mov     $E,16($ctx)
+       jmp     .Loop_avx
+
+.align 16
+.Ldone_avx:
+___
+                               $jj=$j=$saved_j; @V=@saved_V;
+                               $r=$saved_r;     @rndkey=@saved_rndkey;
+
+       &Xtail_avx(\&body_20_39);
+       &Xtail_avx(\&body_20_39);
+       &Xtail_avx(\&body_20_39);
+
+$code.=<<___;
+       vmovups $iv,48($out,$in0)               # write output
+       mov     88(%rsp),$ivp                   # restore $ivp
+
+       add     0($ctx),$A                      # update context
+       add     4($ctx),@T[0]
+       add     8($ctx),$C
+       mov     $A,0($ctx)
+       add     12($ctx),$D
+       mov     @T[0],4($ctx)
+       add     16($ctx),$E
+       mov     $C,8($ctx)
+       mov     $D,12($ctx)
+       mov     $E,16($ctx)
+       vmovups $iv,($ivp)                      # write IV
+       vzeroall
+___
+$code.=<<___ if ($win64);
+       movaps  96+0(%rsp),%xmm6
+       movaps  96+16(%rsp),%xmm7
+       movaps  96+32(%rsp),%xmm8
+       movaps  96+48(%rsp),%xmm9
+       movaps  96+64(%rsp),%xmm10
+       movaps  96+80(%rsp),%xmm11
+       movaps  96+96(%rsp),%xmm12
+       movaps  96+112(%rsp),%xmm13
+       movaps  96+128(%rsp),%xmm14
+       movaps  96+144(%rsp),%xmm15
+___
+$code.=<<___;
+       lea     `104+($win64?10*16:0)`(%rsp),%rsi
+       mov     0(%rsi),%r15
+       mov     8(%rsi),%r14
+       mov     16(%rsi),%r13
+       mov     24(%rsi),%r12
+       mov     32(%rsi),%rbp
+       mov     40(%rsi),%rbx
+       lea     48(%rsi),%rsp
+.Lepilogue_avx:
+       ret
+.size  aesni_cbc_sha1_enc_avx,.-aesni_cbc_sha1_enc_avx
+___
+}
+$code.=<<___;
+.align 64
+K_XX_XX:
+.long  0x5a827999,0x5a827999,0x5a827999,0x5a827999     # K_00_19
+.long  0x6ed9eba1,0x6ed9eba1,0x6ed9eba1,0x6ed9eba1     # K_20_39
+.long  0x8f1bbcdc,0x8f1bbcdc,0x8f1bbcdc,0x8f1bbcdc     # K_40_59
+.long  0xca62c1d6,0xca62c1d6,0xca62c1d6,0xca62c1d6     # K_60_79
+.long  0x00010203,0x04050607,0x08090a0b,0x0c0d0e0f     # pbswap mask
+
+.asciz "AESNI-CBC+SHA1 stitch for x86_64, CRYPTOGAMS by <appro\@openssl.org>"
+.align 64
+___
+
+# EXCEPTION_DISPOSITION handler (EXCEPTION_RECORD *rec,ULONG64 frame,
+#              CONTEXT *context,DISPATCHER_CONTEXT *disp)
+if ($win64) {
+$rec="%rcx";
+$frame="%rdx";
+$context="%r8";
+$disp="%r9";
+
+$code.=<<___;
+.extern        __imp_RtlVirtualUnwind
+.type  ssse3_handler,\@abi-omnipotent
+.align 16
+ssse3_handler:
+       push    %rsi
+       push    %rdi
+       push    %rbx
+       push    %rbp
+       push    %r12
+       push    %r13
+       push    %r14
+       push    %r15
+       pushfq
+       sub     \$64,%rsp
+
+       mov     120($context),%rax      # pull context->Rax
+       mov     248($context),%rbx      # pull context->Rip
+
+       mov     8($disp),%rsi           # disp->ImageBase
+       mov     56($disp),%r11          # disp->HandlerData
+
+       mov     0(%r11),%r10d           # HandlerData[0]
+       lea     (%rsi,%r10),%r10        # prologue label
+       cmp     %r10,%rbx               # context->Rip<prologue label
+       jb      .Lcommon_seh_tail
+
+       mov     152($context),%rax      # pull context->Rsp
+
+       mov     4(%r11),%r10d           # HandlerData[1]
+       lea     (%rsi,%r10),%r10        # epilogue label
+       cmp     %r10,%rbx               # context->Rip>=epilogue label
+       jae     .Lcommon_seh_tail
+
+       lea     96(%rax),%rsi
+       lea     512($context),%rdi      # &context.Xmm6
+       mov     \$20,%ecx
+       .long   0xa548f3fc              # cld; rep movsq
+       lea     `104+10*16`(%rax),%rax  # adjust stack pointer
+
+       mov     0(%rax),%r15
+       mov     8(%rax),%r14
+       mov     16(%rax),%r13
+       mov     24(%rax),%r12
+       mov     32(%rax),%rbp
+       mov     40(%rax),%rbx
+       lea     48(%rax),%rax
+       mov     %rbx,144($context)      # restore context->Rbx
+       mov     %rbp,160($context)      # restore context->Rbp
+       mov     %r12,216($context)      # restore context->R12
+       mov     %r13,224($context)      # restore context->R13
+       mov     %r14,232($context)      # restore context->R14
+       mov     %r15,240($context)      # restore context->R15
+
+.Lcommon_seh_tail:
+       mov     8(%rax),%rdi
+       mov     16(%rax),%rsi
+       mov     %rax,152($context)      # restore context->Rsp
+       mov     %rsi,168($context)      # restore context->Rsi
+       mov     %rdi,176($context)      # restore context->Rdi
+
+       mov     40($disp),%rdi          # disp->ContextRecord
+       mov     $context,%rsi           # context
+       mov     \$154,%ecx              # sizeof(CONTEXT)
+       .long   0xa548f3fc              # cld; rep movsq
+
+       mov     $disp,%rsi
+       xor     %rcx,%rcx               # arg1, UNW_FLAG_NHANDLER
+       mov     8(%rsi),%rdx            # arg2, disp->ImageBase
+       mov     0(%rsi),%r8             # arg3, disp->ControlPc
+       mov     16(%rsi),%r9            # arg4, disp->FunctionEntry
+       mov     40(%rsi),%r10           # disp->ContextRecord
+       lea     56(%rsi),%r11           # &disp->HandlerData
+       lea     24(%rsi),%r12           # &disp->EstablisherFrame
+       mov     %r10,32(%rsp)           # arg5
+       mov     %r11,40(%rsp)           # arg6
+       mov     %r12,48(%rsp)           # arg7
+       mov     %rcx,56(%rsp)           # arg8, (NULL)
+       call    *__imp_RtlVirtualUnwind(%rip)
+
+       mov     \$1,%eax                # ExceptionContinueSearch
+       add     \$64,%rsp
+       popfq
+       pop     %r15
+       pop     %r14
+       pop     %r13
+       pop     %r12
+       pop     %rbp
+       pop     %rbx
+       pop     %rdi
+       pop     %rsi
+       ret
+.size  ssse3_handler,.-ssse3_handler
+
+.section       .pdata
+.align 4
+       .rva    .LSEH_begin_aesni_cbc_sha1_enc_ssse3
+       .rva    .LSEH_end_aesni_cbc_sha1_enc_ssse3
+       .rva    .LSEH_info_aesni_cbc_sha1_enc_ssse3
+___
+$code.=<<___ if ($avx);
+       .rva    .LSEH_begin_aesni_cbc_sha1_enc_avx
+       .rva    .LSEH_end_aesni_cbc_sha1_enc_avx
+       .rva    .LSEH_info_aesni_cbc_sha1_enc_avx
+___
+$code.=<<___;
+.section       .xdata
+.align 8
+.LSEH_info_aesni_cbc_sha1_enc_ssse3:
+       .byte   9,0,0,0
+       .rva    ssse3_handler
+       .rva    .Lprologue_ssse3,.Lepilogue_ssse3       # HandlerData[]
+___
+$code.=<<___ if ($avx);
+.LSEH_info_aesni_cbc_sha1_enc_avx:
+       .byte   9,0,0,0
+       .rva    ssse3_handler
+       .rva    .Lprologue_avx,.Lepilogue_avx           # HandlerData[]
+___
+}
+
+####################################################################
+sub rex {
+  local *opcode=shift;
+  my ($dst,$src)=@_;
+  my $rex=0;
+
+    $rex|=0x04                 if($dst>=8);
+    $rex|=0x01                 if($src>=8);
+    push @opcode,$rex|0x40     if($rex);
+}
+
+sub aesni {
+  my $line=shift;
+  my @opcode=(0x66);
+
+    if ($line=~/(aes[a-z]+)\s+%xmm([0-9]+),\s*%xmm([0-9]+)/) {
+       my %opcodelet = (
+               "aesenc" => 0xdc,       "aesenclast" => 0xdd
+       );
+       return undef if (!defined($opcodelet{$1}));
+       rex(\@opcode,$3,$2);
+       push @opcode,0x0f,0x38,$opcodelet{$1};
+       push @opcode,0xc0|($2&7)|(($3&7)<<3);   # ModR/M
+       return ".byte\t".join(',',@opcode);
+    }
+    return $line;
+}
+
+$code =~ s/\`([^\`]*)\`/eval($1)/gem;
+$code =~ s/\b(aes.*%xmm[0-9]+).*$/aesni($1)/gem;
+
+print $code;
+close STDOUT;
diff --git a/crypto/openssl/crypto/aes/asm/aesni-x86.pl b/crypto/openssl/crypto/aes/asm/aesni-x86.pl
new file mode 100644 (file)
index 0000000..3dc345b
--- /dev/null
@@ -0,0 +1,2189 @@
+#!/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/.
+# ====================================================================
+#
+# This module implements support for Intel AES-NI extension. In
+# OpenSSL context it's used with Intel engine, but can also be used as
+# drop-in replacement for crypto/aes/asm/aes-586.pl [see below for
+# details].
+#
+# Performance.
+#
+# To start with see corresponding paragraph in aesni-x86_64.pl...
+# Instead of filling table similar to one found there I've chosen to
+# summarize *comparison* results for raw ECB, CTR and CBC benchmarks.
+# The simplified table below represents 32-bit performance relative
+# to 64-bit one in every given point. Ratios vary for different
+# encryption modes, therefore interval values.
+#
+#      16-byte     64-byte     256-byte    1-KB        8-KB
+#      53-67%      67-84%      91-94%      95-98%      97-99.5%
+#
+# Lower ratios for smaller block sizes are perfectly understandable,
+# because function call overhead is higher in 32-bit mode. Largest
+# 8-KB block performance is virtually same: 32-bit code is less than
+# 1% slower for ECB, CBC and CCM, and ~3% slower otherwise.
+
+# January 2011
+#
+# See aesni-x86_64.pl for details. Unlike x86_64 version this module
+# interleaves at most 6 aes[enc|dec] instructions, because there are
+# not enough registers for 8x interleave [which should be optimal for
+# Sandy Bridge]. Actually, performance results for 6x interleave
+# factor presented in aesni-x86_64.pl (except for CTR) are for this
+# module.
+
+# April 2011
+#
+# Add aesni_xts_[en|de]crypt. Westmere spends 1.50 cycles processing
+# one byte out of 8KB with 128-bit key, Sandy Bridge - 1.09.
+
+$PREFIX="aesni";       # if $PREFIX is set to "AES", the script
+                       # generates drop-in replacement for
+                       # crypto/aes/asm/aes-586.pl:-)
+$inline=1;             # inline _aesni_[en|de]crypt
+
+$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
+push(@INC,"${dir}","${dir}../../perlasm");
+require "x86asm.pl";
+
+&asm_init($ARGV[0],$0);
+
+if ($PREFIX eq "aesni")        { $movekey=*movups; }
+else                   { $movekey=*movups; }
+
+$len="eax";
+$rounds="ecx";
+$key="edx";
+$inp="esi";
+$out="edi";
+$rounds_="ebx";        # backup copy for $rounds
+$key_="ebp";   # backup copy for $key
+
+$rndkey0="xmm0";
+$rndkey1="xmm1";
+$inout0="xmm2";
+$inout1="xmm3";
+$inout2="xmm4";
+$inout3="xmm5";        $in1="xmm5";
+$inout4="xmm6";        $in0="xmm6";
+$inout5="xmm7";        $ivec="xmm7";
+
+# AESNI extenstion
+sub aeskeygenassist
+{ my($dst,$src,$imm)=@_;
+    if ("$dst:$src" =~ /xmm([0-7]):xmm([0-7])/)
+    {  &data_byte(0x66,0x0f,0x3a,0xdf,0xc0|($1<<3)|$2,$imm);   }
+}
+sub aescommon
+{ my($opcodelet,$dst,$src)=@_;
+    if ("$dst:$src" =~ /xmm([0-7]):xmm([0-7])/)
+    {  &data_byte(0x66,0x0f,0x38,$opcodelet,0xc0|($1<<3)|$2);}
+}
+sub aesimc     { aescommon(0xdb,@_); }
+sub aesenc     { aescommon(0xdc,@_); }
+sub aesenclast { aescommon(0xdd,@_); }
+sub aesdec     { aescommon(0xde,@_); }
+sub aesdeclast { aescommon(0xdf,@_); }
+\f
+# Inline version of internal aesni_[en|de]crypt1
+{ my $sn;
+sub aesni_inline_generate1
+{ my ($p,$inout,$ivec)=@_; $inout=$inout0 if (!defined($inout));
+  $sn++;
+
+    &$movekey          ($rndkey0,&QWP(0,$key));
+    &$movekey          ($rndkey1,&QWP(16,$key));
+    &xorps             ($ivec,$rndkey0)        if (defined($ivec));
+    &lea               ($key,&DWP(32,$key));
+    &xorps             ($inout,$ivec)          if (defined($ivec));
+    &xorps             ($inout,$rndkey0)       if (!defined($ivec));
+    &set_label("${p}1_loop_$sn");
+       eval"&aes${p}   ($inout,$rndkey1)";
+       &dec            ($rounds);
+       &$movekey       ($rndkey1,&QWP(0,$key));
+       &lea            ($key,&DWP(16,$key));
+    &jnz               (&label("${p}1_loop_$sn"));
+    eval"&aes${p}last  ($inout,$rndkey1)";
+}}
+
+sub aesni_generate1    # fully unrolled loop
+{ my ($p,$inout)=@_; $inout=$inout0 if (!defined($inout));
+
+    &function_begin_B("_aesni_${p}rypt1");
+       &movups         ($rndkey0,&QWP(0,$key));
+       &$movekey       ($rndkey1,&QWP(0x10,$key));
+       &xorps          ($inout,$rndkey0);
+       &$movekey       ($rndkey0,&QWP(0x20,$key));
+       &lea            ($key,&DWP(0x30,$key));
+       &cmp            ($rounds,11);
+       &jb             (&label("${p}128"));
+       &lea            ($key,&DWP(0x20,$key));
+       &je             (&label("${p}192"));
+       &lea            ($key,&DWP(0x20,$key));
+       eval"&aes${p}   ($inout,$rndkey1)";
+       &$movekey       ($rndkey1,&QWP(-0x40,$key));
+       eval"&aes${p}   ($inout,$rndkey0)";
+       &$movekey       ($rndkey0,&QWP(-0x30,$key));
+    &set_label("${p}192");
+       eval"&aes${p}   ($inout,$rndkey1)";
+       &$movekey       ($rndkey1,&QWP(-0x20,$key));
+       eval"&aes${p}   ($inout,$rndkey0)";
+       &$movekey       ($rndkey0,&QWP(-0x10,$key));
+    &set_label("${p}128");
+       eval"&aes${p}   ($inout,$rndkey1)";
+       &$movekey       ($rndkey1,&QWP(0,$key));
+       eval"&aes${p}   ($inout,$rndkey0)";
+       &$movekey       ($rndkey0,&QWP(0x10,$key));
+       eval"&aes${p}   ($inout,$rndkey1)";
+       &$movekey       ($rndkey1,&QWP(0x20,$key));
+       eval"&aes${p}   ($inout,$rndkey0)";
+       &$movekey       ($rndkey0,&QWP(0x30,$key));
+       eval"&aes${p}   ($inout,$rndkey1)";
+       &$movekey       ($rndkey1,&QWP(0x40,$key));
+       eval"&aes${p}   ($inout,$rndkey0)";
+       &$movekey       ($rndkey0,&QWP(0x50,$key));
+       eval"&aes${p}   ($inout,$rndkey1)";
+       &$movekey       ($rndkey1,&QWP(0x60,$key));
+       eval"&aes${p}   ($inout,$rndkey0)";
+       &$movekey       ($rndkey0,&QWP(0x70,$key));
+       eval"&aes${p}   ($inout,$rndkey1)";
+    eval"&aes${p}last  ($inout,$rndkey0)";
+    &ret();
+    &function_end_B("_aesni_${p}rypt1");
+}
+\f
+# void $PREFIX_encrypt (const void *inp,void *out,const AES_KEY *key);
+&aesni_generate1("enc") if (!$inline);
+&function_begin_B("${PREFIX}_encrypt");
+       &mov    ("eax",&wparam(0));
+       &mov    ($key,&wparam(2));
+       &movups ($inout0,&QWP(0,"eax"));
+       &mov    ($rounds,&DWP(240,$key));
+       &mov    ("eax",&wparam(1));
+       if ($inline)
+       {   &aesni_inline_generate1("enc");     }
+       else
+       {   &call       ("_aesni_encrypt1");    }
+       &movups (&QWP(0,"eax"),$inout0);
+       &ret    ();
+&function_end_B("${PREFIX}_encrypt");
+
+# void $PREFIX_decrypt (const void *inp,void *out,const AES_KEY *key);
+&aesni_generate1("dec") if(!$inline);
+&function_begin_B("${PREFIX}_decrypt");
+       &mov    ("eax",&wparam(0));
+       &mov    ($key,&wparam(2));
+       &movups ($inout0,&QWP(0,"eax"));
+       &mov    ($rounds,&DWP(240,$key));
+       &mov    ("eax",&wparam(1));
+       if ($inline)
+       {   &aesni_inline_generate1("dec");     }
+       else
+       {   &call       ("_aesni_decrypt1");    }
+       &movups (&QWP(0,"eax"),$inout0);
+       &ret    ();
+&function_end_B("${PREFIX}_decrypt");
+
+# _aesni_[en|de]cryptN are private interfaces, N denotes interleave
+# factor. Why 3x subroutine were originally used in loops? Even though
+# aes[enc|dec] latency was originally 6, it could be scheduled only
+# every *2nd* cycle. Thus 3x interleave was the one providing optimal
+# utilization, i.e. when subroutine's throughput is virtually same as
+# of non-interleaved subroutine [for number of input blocks up to 3].
+# This is why it makes no sense to implement 2x subroutine.
+# aes[enc|dec] latency in next processor generation is 8, but the
+# instructions can be scheduled every cycle. Optimal interleave for
+# new processor is therefore 8x, but it's unfeasible to accommodate it
+# in XMM registers addreassable in 32-bit mode and therefore 6x is
+# used instead...
+
+sub aesni_generate3
+{ my $p=shift;
+
+    &function_begin_B("_aesni_${p}rypt3");
+       &$movekey       ($rndkey0,&QWP(0,$key));
+       &shr            ($rounds,1);
+       &$movekey       ($rndkey1,&QWP(16,$key));
+       &lea            ($key,&DWP(32,$key));
+       &xorps          ($inout0,$rndkey0);
+       &pxor           ($inout1,$rndkey0);
+       &pxor           ($inout2,$rndkey0);
+       &$movekey       ($rndkey0,&QWP(0,$key));
+
+    &set_label("${p}3_loop");
+       eval"&aes${p}   ($inout0,$rndkey1)";
+       eval"&aes${p}   ($inout1,$rndkey1)";
+       &dec            ($rounds);
+       eval"&aes${p}   ($inout2,$rndkey1)";
+       &$movekey       ($rndkey1,&QWP(16,$key));
+       eval"&aes${p}   ($inout0,$rndkey0)";
+       eval"&aes${p}   ($inout1,$rndkey0)";
+       &lea            ($key,&DWP(32,$key));
+       eval"&aes${p}   ($inout2,$rndkey0)";
+       &$movekey       ($rndkey0,&QWP(0,$key));
+       &jnz            (&label("${p}3_loop"));
+    eval"&aes${p}      ($inout0,$rndkey1)";
+    eval"&aes${p}      ($inout1,$rndkey1)";
+    eval"&aes${p}      ($inout2,$rndkey1)";
+    eval"&aes${p}last  ($inout0,$rndkey0)";
+    eval"&aes${p}last  ($inout1,$rndkey0)";
+    eval"&aes${p}last  ($inout2,$rndkey0)";
+    &ret();
+    &function_end_B("_aesni_${p}rypt3");
+}
+
+# 4x interleave is implemented to improve small block performance,
+# most notably [and naturally] 4 block by ~30%. One can argue that one
+# should have implemented 5x as well, but improvement  would be <20%,
+# so it's not worth it...
+sub aesni_generate4
+{ my $p=shift;
+
+    &function_begin_B("_aesni_${p}rypt4");
+       &$movekey       ($rndkey0,&QWP(0,$key));
+       &$movekey       ($rndkey1,&QWP(16,$key));
+       &shr            ($rounds,1);
+       &lea            ($key,&DWP(32,$key));
+       &xorps          ($inout0,$rndkey0);
+       &pxor           ($inout1,$rndkey0);
+       &pxor           ($inout2,$rndkey0);
+       &pxor           ($inout3,$rndkey0);
+       &$movekey       ($rndkey0,&QWP(0,$key));
+
+    &set_label("${p}4_loop");
+       eval"&aes${p}   ($inout0,$rndkey1)";
+       eval"&aes${p}   ($inout1,$rndkey1)";
+       &dec            ($rounds);
+       eval"&aes${p}   ($inout2,$rndkey1)";
+       eval"&aes${p}   ($inout3,$rndkey1)";
+       &$movekey       ($rndkey1,&QWP(16,$key));
+       eval"&aes${p}   ($inout0,$rndkey0)";
+       eval"&aes${p}   ($inout1,$rndkey0)";
+       &lea            ($key,&DWP(32,$key));
+       eval"&aes${p}   ($inout2,$rndkey0)";
+       eval"&aes${p}   ($inout3,$rndkey0)";
+       &$movekey       ($rndkey0,&QWP(0,$key));
+    &jnz               (&label("${p}4_loop"));
+
+    eval"&aes${p}      ($inout0,$rndkey1)";
+    eval"&aes${p}      ($inout1,$rndkey1)";
+    eval"&aes${p}      ($inout2,$rndkey1)";
+    eval"&aes${p}      ($inout3,$rndkey1)";
+    eval"&aes${p}last  ($inout0,$rndkey0)";
+    eval"&aes${p}last  ($inout1,$rndkey0)";
+    eval"&aes${p}last  ($inout2,$rndkey0)";
+    eval"&aes${p}last  ($inout3,$rndkey0)";
+    &ret();
+    &function_end_B("_aesni_${p}rypt4");
+}
+
+sub aesni_generate6
+{ my $p=shift;
+
+    &function_begin_B("_aesni_${p}rypt6");
+    &static_label("_aesni_${p}rypt6_enter");
+       &$movekey       ($rndkey0,&QWP(0,$key));
+       &shr            ($rounds,1);
+       &$movekey       ($rndkey1,&QWP(16,$key));
+       &lea            ($key,&DWP(32,$key));
+       &xorps          ($inout0,$rndkey0);
+       &pxor           ($inout1,$rndkey0);     # pxor does better here
+       eval"&aes${p}   ($inout0,$rndkey1)";
+       &pxor           ($inout2,$rndkey0);
+       eval"&aes${p}   ($inout1,$rndkey1)";
+       &pxor           ($inout3,$rndkey0);
+       &dec            ($rounds);
+       eval"&aes${p}   ($inout2,$rndkey1)";
+       &pxor           ($inout4,$rndkey0);
+       eval"&aes${p}   ($inout3,$rndkey1)";
+       &pxor           ($inout5,$rndkey0);
+     &