summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChen, Chih-Chia <pigfoot@gmail.com>2016-01-06 15:59:30 +0800
committerChen, Chih-Chia <pigfoot@gmail.com>2016-01-06 16:10:55 +0800
commit877199133678274b60a476a6571475251478ae5b (patch)
tree0b2c62358c37979c60412fdb744c928746264f2d
parentPass Gentoo's QA tests (diff)
downloadpigfoot-877199133678274b60a476a6571475251478ae5b.tar.gz
pigfoot-877199133678274b60a476a6571475251478ae5b.tar.bz2
pigfoot-877199133678274b60a476a6571475251478ae5b.zip
Add openssl (v1.0.2e) with cloudflare's chacha20_poly1305 patch
Patch is stolen from https://github.com/cloudflare/sslconfig/blob/0aebbd268424ef69a017d8987bf12a2f3a0c3670/patches/openssl__chacha20_poly1305_cf.patch
-rw-r--r--dev-libs/openssl/Manifest14
-rwxr-xr-xdev-libs/openssl/files/gentoo.config-1.0.2165
-rw-r--r--dev-libs/openssl/files/openssl-1.0.0a-ldflags.patch29
-rw-r--r--dev-libs/openssl/files/openssl-1.0.0d-windres.patch76
-rw-r--r--dev-libs/openssl/files/openssl-1.0.1p-default-source.patch30
-rw-r--r--dev-libs/openssl/files/openssl-1.0.2-ipv6.patch611
-rw-r--r--dev-libs/openssl/files/openssl-1.0.2a-parallel-install-dirs.patch64
-rw-r--r--dev-libs/openssl/files/openssl-1.0.2a-parallel-obj-headers.patch37
-rw-r--r--dev-libs/openssl/files/openssl-1.0.2a-parallel-symlinking.patch63
-rw-r--r--dev-libs/openssl/files/openssl-1.0.2a-x32-asm.patch43
-rw-r--r--dev-libs/openssl/files/openssl-1.0.2e-chacha20_poly1305_cf.patch4462
-rw-r--r--dev-libs/openssl/files/openssl-1.0.2e-parallel-build.patch314
-rw-r--r--dev-libs/openssl/metadata.xml10
-rw-r--r--dev-libs/openssl/openssl-1.0.2e.ebuild269
14 files changed, 6187 insertions, 0 deletions
diff --git a/dev-libs/openssl/Manifest b/dev-libs/openssl/Manifest
new file mode 100644
index 0000000..69881f7
--- /dev/null
+++ b/dev-libs/openssl/Manifest
@@ -0,0 +1,14 @@
+AUX gentoo.config-1.0.2 4905 SHA256 98a4c1e2cef5a2378d5dcc61f661300333a6c5c0ba4e3c82590f688e33117604 SHA512 4c13371fb7d0c33f015ed559951c755dabc35279c91d7490578a008087f62c1a94d69e309d4a113bf23e5ad7085e2eec5692152b3d7b1c3130cb64dc2a002632 WHIRLPOOL 64d9cc378ff32bb78a8d0edea25b6519c65af5faf3a7b22713bf19881f61385271e352814460f16375effeccc743c82642e8175aa2590f352b2909748513e120
+AUX openssl-1.0.0a-ldflags.patch 1095 SHA256 17bb0b9988de0be6b8bb916d953d5d62cf054943f3bc24c5d7c8fea91d864350 SHA512 80c3677313a6268fdc2eb7b556dc081f1047694cf932a8669820923952bf0e3002da4cd92d6a335b44f8a6ece7d88319c15e9c0171118bfc03ff7a9b718726d8 WHIRLPOOL 55bc5d8f0ee620d8e56215572a6eb65a06ff9bf180d6b33f6db74e2129e5373252238772ba6db25293f398a6713b7259c6ae959b15ce8292da9aeb3071a34243
+AUX openssl-1.0.0d-windres.patch 2912 SHA256 e5dbfd6af69bc3f69b51787cf1f6245207be9824dfffbdd9b4e278772ed8ab32 SHA512 d7a0238edea29aac7d20dca0778c67f8ae4dc0da190e5277e1b3519ae536f2c44533ac5dc1cbcd138bc4277ad669b13fca316bd962f26e2cb387f2ad3fd0111b WHIRLPOOL d62156820e55898d0a0393473c6ad8e49c5aa7bb9d3fc7043795de7102c3003d5f8b874c751e03cf832e306ac290790e871e1318bb830b3558a43e09be5b45b4
+AUX openssl-1.0.1p-default-source.patch 861 SHA256 390b6857e76cd0513a089ff3eeed60097c3b30bec4b004bb6adbb8eaab02dc4a SHA512 cbd47ae5553ec0e683a92171cb1c2e68d7eb0cf2b1787e3fe332ca2df0aefa31a1a74d60345d5e42d00bdda439019d089560cf2f5464dfe19ff7a3d6a310d06b WHIRLPOOL d734c8776c2d4f17a562f580f676de08bf35e07b04005f1c2a6e7f2752e3a1b57f6d771195f84d7d9709bf2e669b119fe3ae37e473de192e9c10a8ffb1c8969f
+AUX openssl-1.0.2-ipv6.patch 18811 SHA256 9ff3150c75f3f3e6a9773ffe54d90994cbf68cc919134aea68e09e7ed921763d SHA512 58e293f8f19a3fad08729b842dd977b73fedb0c49208d87a056bfea857c0e2b79a310d7d098c04429b65564fce64defeda6d1dcc3068ad5a80ef276db6421e54 WHIRLPOOL 36a0fffc7238011b93077bed94c9507f2ffc1cf199e6c06e94d01589cdc84a6568b9122e1a120b8262bd0a1c43f25169a29796c92a78338dd9f03b4cc2cdf0b8
+AUX openssl-1.0.2a-parallel-install-dirs.patch 2013 SHA256 eddd8a5123748052c598214487ac178e4bfa4e31ba2ec520c70d59c8c5bfa2e9 SHA512 c3b97fa318b9627bcaf4f39d1615c46322c1081cded135af5b5115beb2be74ead46084119fce5643b12c54b6851c33bfb624694ccf6f3d32060b6d56239d3674 WHIRLPOOL 59228ad2796e28edf7508a3b3bbdab36f7b678922566a1ed43a86727371c7b6b8c362431f49812e7c60a9aa72134d7fffaeb7be0efb6b5ca0f10e1c716b6a557
+AUX openssl-1.0.2a-parallel-obj-headers.patch 1359 SHA256 147c3eeaad614c044749ea527cb433eae5e2d5cad34a78c6ba61cd967bfbe01f SHA512 ac8224bc088099d72e7e6761303b8653766372bd027536951c458bd22fd0526163de22bf27675e0292a12ae7257a5c1edf26a92747e00cc139e13e1b624b4072 WHIRLPOOL 58b1de7c90ed96a077065ff6abfdeaffd98ce68cc9a2551dab7ff3d04e9b38be8d4bb94a6830f4e6c3d997747345c43f76c31f4c7b825f56fd488e85b9c6179e
+AUX openssl-1.0.2a-parallel-symlinking.patch 2041 SHA256 30cb49489de5041841a74da9155cd4fabfbce33237262ba7cd23974314ae2956 SHA512 b87ab581784c285ef394b31baa1196a831a86c3b2d578704c9d8b80d68c70a8b19cfa88bd29b84578ed024135ae2d2ac4d622c91e1040074016b8fd104d6c05a WHIRLPOOL c8200ec6755efdce550afd2f59b3d5dc36324c6810b3ae7427af7130be9ba0db5857c13811f97dd6672230b9f096f81ebb4136c9589d53d25dcfe5c064355a46
+AUX openssl-1.0.2a-x32-asm.patch 1561 SHA256 8bcff04217c5ad82448e27d14f3559a157c2cad89b5fb2b6af701fff1664f86d SHA512 fbb23393e68776e9d34953f85ba3cbb285421d50f06bd297b485c7cffc8d89ca8caff6783f21038ae668b5c75056c89dc652217ac8609b5328e2c28e70ac294c WHIRLPOOL 70163beaed966de948562c3a633828846d12eda7b04526c7e33746c67af5a20ecf47e9e9e5cce33abf7444676f4b15b770204e95db75d0b91a9db13c46ff92bb
+AUX openssl-1.0.2e-chacha20_poly1305_cf.patch 142425 SHA256 ce062e692dfd7a4f783f8909167c34903b222911a4c97d819983f5075def9398 SHA512 80946128052a5d120fea510332ea4532e327738c16eabf2565b9c5da46e61a5ac274e1f10f2c00b12f36592ee3d27454ccd6b3112a4aa993eebd8803271d25a6 WHIRLPOOL be1c6cef8434a0957a367167e61d2d03f5850559d54c8e74260dfcea3f5251135b2290517722ea3b5b010e7cce9cd75592d4fb1ddc194cdf725dca569b0e289f
+AUX openssl-1.0.2e-parallel-build.patch 9620 SHA256 1200c48f8e209bce505bec23958afa4700681ee97f374064a5484623fe497269 SHA512 8aa64a78bc190a9c04f0093af2cdbcc0bed25be8c5f31c3a31e8b19954a58ba96ab05139d3ae6ecd7bc24e123536eec54fc98330167affcfd13cbd6d90626637 WHIRLPOOL 7ad5e275dce8f644deb3779900940cdbc625ecdcc984386502e1cb8dd7ead6bbd3a32fa41ae537a7ad5b2dc8308a2458ebbfcd3c05aedc4874e5d5a212677f88
+DIST openssl-1.0.2e.tar.gz 5256555 SHA256 e23ccafdb75cfcde782da0151731aa2185195ac745eea3846133f2e05c0e0bff SHA512 b73f114a117ccab284cf5891dac050e3016d28e0b1fc71639442cdb42accef676115af90a12deff4bcc1f599cc0cbdeb38142cbf4570bd7d03634786ad32c95f WHIRLPOOL 8e1c1800a66f57fa78dc391e717e4b2bdf0e6e37a837c5ac033d7a4b1a6437451c7e7540c4ec2f75f936a2d2ef4f9293b42c76f51b0c9c93706639589612f196
+EBUILD openssl-1.0.2e.ebuild 8889 SHA256 94d1ec898922de876f0455ce9bedf67c1226d89bd32a4ddf36b1ddae75c09bf8 SHA512 b602036a6c3d832d749cbc8e989322f94c0efb6e7254a96d6926ea9168756d0382ab616eeecb4eda009bf48b35651cf39dcedcac0d8b833cb24a0e20a0f0745e WHIRLPOOL 440652b5076b21ebd435f6204e9d8d75cd3429f9929729849cb40bc9690720c215b4a5e806a8bd00d5860c9a13c1c7cabc686580487a90afa5c7f7926f2cf1c1
+MISC metadata.xml 309 SHA256 25781461d8d8523a4ba8fe3df0362e386486d35448f7dba713a2fd59dc21acd4 SHA512 805ef574465b9ff8d6eeabaaaa4c1ddb29d5064592b2e3d39c82430fa6901769338d8dcea528217caea4395c10f2e9d1f39029db3c71059d899ddba23fe7fa30 WHIRLPOOL 989fefe2e3864108f63cca936f06bf32bd02ab2535f3d70db9d10d54de9d496944e278d73f0e48a4b37c0d153718fc8c1403e9fdeda1477d48dc607467a6e7b1
diff --git a/dev-libs/openssl/files/gentoo.config-1.0.2 b/dev-libs/openssl/files/gentoo.config-1.0.2
new file mode 100755
index 0000000..b3f6ced
--- /dev/null
+++ b/dev-libs/openssl/files/gentoo.config-1.0.2
@@ -0,0 +1,165 @@
+#!/usr/bin/env bash
+# Copyright 1999-2014 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Id$
+#
+# Openssl doesn't play along nicely with cross-compiling
+# like autotools based projects, so let's teach it new tricks.
+#
+# Review the bundled 'config' script to see why kind of targets
+# we can pass to the 'Configure' script.
+
+
+# Testing routines
+if [[ $1 == "test" ]] ; then
+ for c in \
+ "arm-gentoo-linux-uclibc |linux-generic32 -DL_ENDIAN" \
+ "armv5b-linux-gnu |linux-armv4 -DB_ENDIAN" \
+ "x86_64-pc-linux-gnu |linux-x86_64" \
+ "alpha-linux-gnu |linux-alpha-gcc" \
+ "alphaev56-unknown-linux-gnu |linux-alpha+bwx-gcc" \
+ "i686-pc-linux-gnu |linux-elf" \
+ "whatever-gentoo-freebsdX.Y |BSD-generic32" \
+ "i686-gentoo-freebsdX.Y |BSD-x86-elf" \
+ "sparc64-alpha-freebsdX.Y |BSD-sparc64" \
+ "ia64-gentoo-freebsd5.99234 |BSD-ia64" \
+ "x86_64-gentoo-freebsdX.Y |BSD-x86_64" \
+ "hppa64-aldsF-linux-gnu5.3 |linux-generic32 -DB_ENDIAN" \
+ "powerpc-gentOO-linux-uclibc |linux-ppc" \
+ "powerpc64-unk-linux-gnu |linux-ppc64" \
+ "powerpc64le-linux-gnu |linux-ppc64le" \
+ "x86_64-apple-darwinX |darwin64-x86_64-cc" \
+ "powerpc64-apple-darwinX |darwin64-ppc-cc" \
+ "i686-apple-darwinX |darwin-i386-cc" \
+ "i386-apple-darwinX |darwin-i386-cc" \
+ "powerpc-apple-darwinX |darwin-ppc-cc" \
+ "i586-pc-winnt |winnt-parity" \
+ "s390-ibm-linux-gnu |linux-generic32 -DB_ENDIAN" \
+ "s390x-linux-gnu |linux64-s390x" \
+ ;do
+ CHOST=${c/|*}
+ ret_want=${c/*|}
+ ret_got=$(CHOST=${CHOST} "$0")
+
+ if [[ ${ret_want} == "${ret_got}" ]] ; then
+ echo "PASS: ${CHOST}"
+ else
+ echo "FAIL: ${CHOST}"
+ echo -e "\twanted: ${ret_want}"
+ echo -e "\twe got: ${ret_got}"
+ fi
+ done
+ exit 0
+fi
+[[ -z ${CHOST} && -n $1 ]] && CHOST=$1
+
+
+# Detect the operating system
+case ${CHOST} in
+ *-aix*) system="aix";;
+ *-darwin*) system="darwin";;
+ *-freebsd*) system="BSD";;
+ *-hpux*) system="hpux";;
+ *-linux*) system="linux";;
+ *-solaris*) system="solaris";;
+ *-winnt*) system="winnt";;
+ x86_64-*-mingw*) system="mingw64";;
+ *mingw*) system="mingw";;
+ *) exit 0;;
+esac
+
+
+# Compiler munging
+compiler="gcc"
+if [[ ${CC} == "ccc" ]] ; then
+ compiler=${CC}
+fi
+
+
+# Detect target arch
+machine=""
+chost_machine=${CHOST%%-*}
+case ${system} in
+linux)
+ case ${chost_machine}:${ABI} in
+ aarch64*be*) machine="generic64 -DB_ENDIAN";;
+ aarch64*) machine="generic64 -DL_ENDIAN";;
+ alphaev56*|\
+ alphaev[678]*)machine=alpha+bwx-${compiler};;
+ alpha*) machine=alpha-${compiler};;
+ armv[4-9]*b*) machine="armv4 -DB_ENDIAN";;
+ armv[4-9]*) machine="armv4 -DL_ENDIAN";;
+ arm*b*) machine="generic32 -DB_ENDIAN";;
+ arm*) machine="generic32 -DL_ENDIAN";;
+ avr*) machine="generic32 -DL_ENDIAN";;
+ bfin*) machine="generic32 -DL_ENDIAN";;
+ # hppa64*) machine=parisc64;;
+ hppa*) machine="generic32 -DB_ENDIAN";;
+ i[0-9]86*|\
+ x86_64*:x86) machine=elf;;
+ ia64*) machine=ia64;;
+ m68*) machine="generic32 -DB_ENDIAN";;
+ mips*el*) machine="generic32 -DL_ENDIAN";;
+ mips*) machine="generic32 -DB_ENDIAN";;
+ powerpc64*le*)machine=ppc64le;;
+ powerpc64*) machine=ppc64;;
+ powerpc*le*) machine="generic32 -DL_ENDIAN";;
+ powerpc*) machine=ppc;;
+ # sh64*) machine=elf;;
+ sh*b*) machine="generic32 -DB_ENDIAN";;
+ sh*) machine="generic32 -DL_ENDIAN";;
+ sparc*v7*) machine="generic32 -DB_ENDIAN";;
+ sparc64*) machine=sparcv9;;
+ sparc*) machine=sparcv8;;
+ s390x*) machine=s390x system=linux64;;
+ s390*) machine="generic32 -DB_ENDIAN";;
+ x86_64*:x32) machine=x32;;
+ x86_64*) machine=x86_64;;
+ esac
+ ;;
+BSD)
+ case ${chost_machine} in
+ alpha*) machine=generic64;;
+ i[6-9]86*) machine=x86-elf;;
+ ia64*) machine=ia64;;
+ sparc64*) machine=sparc64;;
+ x86_64*) machine=x86_64;;
+ *) machine=generic32;;
+ esac
+ ;;
+aix)
+ machine=${compiler}
+ ;;
+darwin)
+ case ${chost_machine} in
+ powerpc64) machine=ppc-cc; system=${system}64;;
+ powerpc) machine=ppc-cc;;
+ i?86*) machine=i386-cc;;
+ x86_64) machine=x86_64-cc; system=${system}64;;
+ esac
+ ;;
+hpux)
+ case ${chost_machine} in
+ ia64) machine=ia64-${compiler} ;;
+ esac
+ ;;
+solaris)
+ case ${chost_machine} in
+ i386) machine=x86-${compiler} ;;
+ x86_64*) machine=x86_64-${compiler}; system=${system}64;;
+ sparcv9*) machine=sparcv9-${compiler}; system=${system}64;;
+ sparc*) machine=sparcv8-${compiler};;
+ esac
+ ;;
+winnt)
+ machine=parity
+ ;;
+mingw*)
+ # special case ... no xxx-yyy style name
+ echo ${system}
+ ;;
+esac
+
+
+# If we have something, show it
+[[ -n ${machine} ]] && echo ${system}-${machine}
diff --git a/dev-libs/openssl/files/openssl-1.0.0a-ldflags.patch b/dev-libs/openssl/files/openssl-1.0.0a-ldflags.patch
new file mode 100644
index 0000000..c99ef4a
--- /dev/null
+++ b/dev-libs/openssl/files/openssl-1.0.0a-ldflags.patch
@@ -0,0 +1,29 @@
+http://bugs.gentoo.org/181438
+http://bugs.gentoo.org/327421
+https://rt.openssl.org/Ticket/Display.html?id=3331&user=guest&pass=guest
+
+make sure we respect LDFLAGS
+
+also make sure we don't add useless -rpath flags to the system libdir
+
+--- Makefile.org
++++ Makefile.org
+@@ -189,6 +189,7 @@
+ MAKEDEPEND='$$$${TOP}/util/domd $$$${TOP} -MD $(MAKEDEPPROG)' \
+ DEPFLAG='-DOPENSSL_NO_DEPRECATED $(DEPFLAG)' \
+ MAKEDEPPROG='$(MAKEDEPPROG)' \
++ LDFLAGS='${LDFLAGS}' \
+ SHARED_LDFLAGS='$(SHARED_LDFLAGS)' \
+ KRB5_INCLUDES='$(KRB5_INCLUDES)' LIBKRB5='$(LIBKRB5)' \
+ ZLIB_INCLUDE='$(ZLIB_INCLUDE)' LIBZLIB='$(LIBZLIB)' \
+--- Makefile.shared
++++ Makefile.shared
+@@ -153,7 +153,7 @@
+ NOALLSYMSFLAGS='-Wl,--no-whole-archive'; \
+ SHAREDFLAGS="$(CFLAGS) $(SHARED_LDFLAGS) -shared -Wl,-Bsymbolic -Wl,-soname=$$SHLIB$$SHLIB_SOVER$$SHLIB_SUFFIX"
+
+-DO_GNU_APP=LDFLAGS="$(CFLAGS) -Wl,-rpath,$(LIBRPATH)"
++DO_GNU_APP=LDFLAGS="$(LDFLAGS) $(CFLAGS)"
+
+ #This is rather special. It's a special target with which one can link
+ #applications without bothering with any features that have anything to
diff --git a/dev-libs/openssl/files/openssl-1.0.0d-windres.patch b/dev-libs/openssl/files/openssl-1.0.0d-windres.patch
new file mode 100644
index 0000000..0b360d2
--- /dev/null
+++ b/dev-libs/openssl/files/openssl-1.0.0d-windres.patch
@@ -0,0 +1,76 @@
+URL: http://rt.openssl.org/Ticket/Display.html?id=2558&user=guest&pass=guest
+Subject: make windres controllable via build env var settings
+
+atm, the windres code in openssl is only usable via the cross-compile prefix
+option unlike all the other build tools. so add support for the standard $RC
+/ $WINDRES env vars as well.
+
+Index: Configure
+===================================================================
+RCS file: /usr/local/src/openssl/CVSROOT/openssl/Configure,v
+retrieving revision 1.621.2.40
+diff -u -p -r1.621.2.40 Configure
+--- Configure 30 Nov 2010 22:19:26 -0000 1.621.2.40
++++ Configure 4 Jul 2011 23:12:32 -0000
+@@ -1094,6 +1094,7 @@ my $shared_extension = $fields[$idx_shar
+ my $ranlib = $ENV{'RANLIB'} || $fields[$idx_ranlib];
+ my $ar = $ENV{'AR'} || "ar";
+ my $arflags = $fields[$idx_arflags];
++my $windres = $ENV{'RC'} || $ENV{'WINDRES'} || "windres";
+ my $multilib = $fields[$idx_multilib];
+
+ # if $prefix/lib$multilib is not an existing directory, then
+@@ -1511,12 +1512,14 @@ while (<IN>)
+ s/^AR=\s*/AR= \$\(CROSS_COMPILE\)/;
+ s/^NM=\s*/NM= \$\(CROSS_COMPILE\)/;
+ s/^RANLIB=\s*/RANLIB= \$\(CROSS_COMPILE\)/;
++ s/^WINDRES=\s*/WINDRES= \$\(CROSS_COMPILE\)/;
+ s/^MAKEDEPPROG=.*$/MAKEDEPPROG= \$\(CROSS_COMPILE\)$cc/ if $cc eq "gcc";
+ }
+ else {
+ s/^CC=.*$/CC= $cc/;
+ s/^AR=\s*ar/AR= $ar/;
+ s/^RANLIB=.*/RANLIB= $ranlib/;
++ s/^WINDRES=.*/WINDRES= $windres/;
+ s/^MAKEDEPPROG=.*$/MAKEDEPPROG= $cc/ if $cc eq "gcc";
+ }
+ s/^CFLAG=.*$/CFLAG= $cflags/;
+Index: Makefile.org
+===================================================================
+RCS file: /usr/local/src/openssl/CVSROOT/openssl/Makefile.org,v
+retrieving revision 1.295.2.10
+diff -u -p -r1.295.2.10 Makefile.org
+--- Makefile.org 27 Jan 2010 16:06:58 -0000 1.295.2.10
++++ Makefile.org 4 Jul 2011 23:13:08 -0000
+@@ -66,6 +66,7 @@ EXE_EXT=
+ ARFLAGS=
+ AR=ar $(ARFLAGS) r
+ RANLIB= ranlib
++WINDRES= windres
+ NM= nm
+ PERL= perl
+ TAR= tar
+@@ -180,6 +181,7 @@ BUILDENV= PLATFORM='$(PLATFORM)' PROCESS
+ CC='$(CC)' CFLAG='$(CFLAG)' \
+ AS='$(CC)' ASFLAG='$(CFLAG) -c' \
+ AR='$(AR)' NM='$(NM)' RANLIB='$(RANLIB)' \
++ WINDRES='$(WINDRES)' \
+ CROSS_COMPILE='$(CROSS_COMPILE)' \
+ PERL='$(PERL)' ENGDIRS='$(ENGDIRS)' \
+ SDIRS='$(SDIRS)' LIBRPATH='$(INSTALLTOP)/$(LIBDIR)' \
+Index: Makefile.shared
+===================================================================
+RCS file: /usr/local/src/openssl/CVSROOT/openssl/Makefile.shared,v
+retrieving revision 1.72.2.4
+diff -u -p -r1.72.2.4 Makefile.shared
+--- Makefile.shared 21 Aug 2010 11:36:49 -0000 1.72.2.4
++++ Makefile.shared 4 Jul 2011 23:13:52 -0000
+@@ -293,7 +293,7 @@ link_a.cygwin:
+ fi; \
+ dll_name=$$SHLIB$$SHLIB_SOVER$$SHLIB_SUFFIX; \
+ $(PERL) util/mkrc.pl $$dll_name | \
+- $(CROSS_COMPILE)windres -o rc.o; \
++ $(WINDRES) -o rc.o; \
+ extras="$$extras rc.o"; \
+ ALLSYMSFLAGS='-Wl,--whole-archive'; \
+ NOALLSYMSFLAGS='-Wl,--no-whole-archive'; \
diff --git a/dev-libs/openssl/files/openssl-1.0.1p-default-source.patch b/dev-libs/openssl/files/openssl-1.0.1p-default-source.patch
new file mode 100644
index 0000000..7302998
--- /dev/null
+++ b/dev-libs/openssl/files/openssl-1.0.1p-default-source.patch
@@ -0,0 +1,30 @@
+https://bugs.gentoo.org/554338
+https://rt.openssl.org/Ticket/Display.html?id=3934&user=guest&pass=guest
+
+From 7c2e97f8bbae517496fdc11f475b4ae54b2534f5 Mon Sep 17 00:00:00 2001
+From: Mike Frysinger <vapier@gentoo.org>
+Date: Fri, 10 Jul 2015 01:50:52 -0400
+Subject: [PATCH] test: use _DEFAULT_SOURCE with newer glibc versions
+
+The _BSD_SOURCE macro is replaced by the _DEFAULT_SOURCE macro. Using
+just the former with newer versions leads to a build time warning, so
+make sure to use the new macro too.
+---
+ ssl/ssltest.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/ssl/ssltest.c b/ssl/ssltest.c
+index 26cf96c..b36f667 100644
+--- a/ssl/ssltest.c
++++ b/ssl/ssltest.c
+@@ -141,6 +141,7 @@
+ */
+
+ /* Or gethostname won't be declared properly on Linux and GNU platforms. */
++#define _DEFAULT_SOURCE 1
+ #define _BSD_SOURCE 1
+
+ #include <assert.h>
+--
+2.4.4
+
diff --git a/dev-libs/openssl/files/openssl-1.0.2-ipv6.patch b/dev-libs/openssl/files/openssl-1.0.2-ipv6.patch
new file mode 100644
index 0000000..27574ea
--- /dev/null
+++ b/dev-libs/openssl/files/openssl-1.0.2-ipv6.patch
@@ -0,0 +1,611 @@
+http://rt.openssl.org/Ticket/Display.html?id=2051&user=guest&pass=guest
+
+--- openssl-1.0.2/apps/s_apps.h
++++ openssl-1.0.2/apps/s_apps.h
+@@ -154,7 +154,7 @@
+ int do_server(int port, int type, int *ret,
+ int (*cb) (char *hostname, int s, int stype,
+ unsigned char *context), unsigned char *context,
+- int naccept);
++ int naccept, int use_ipv4, int use_ipv6);
+ #ifdef HEADER_X509_H
+ int MS_CALLBACK verify_callback(int ok, X509_STORE_CTX *ctx);
+ #endif
+@@ -167,7 +167,8 @@
+ int ssl_print_curves(BIO *out, SSL *s, int noshared);
+ #endif
+ int ssl_print_tmp_key(BIO *out, SSL *s);
+-int init_client(int *sock, char *server, int port, int type);
++int init_client(int *sock, char *server, int port, int type,
++ int use_ipv4, int use_ipv6);
+ int should_retry(int i);
+ int extract_port(char *str, short *port_ptr);
+ int extract_host_port(char *str, char **host_ptr, unsigned char *ip,
+--- openssl-1.0.2/apps/s_client.c
++++ openssl-1.0.2/apps/s_client.c
+@@ -302,6 +302,10 @@
+ {
+ BIO_printf(bio_err, "usage: s_client args\n");
+ BIO_printf(bio_err, "\n");
++ BIO_printf(bio_err, " -4 - use IPv4 only\n");
++#if OPENSSL_USE_IPV6
++ BIO_printf(bio_err, " -6 - use IPv6 only\n");
++#endif
+ BIO_printf(bio_err, " -host host - use -connect instead\n");
+ BIO_printf(bio_err, " -port port - use -connect instead\n");
+ BIO_printf(bio_err,
+@@ -658,6 +662,7 @@
+ int sbuf_len, sbuf_off;
+ fd_set readfds, writefds;
+ short port = PORT;
++ int use_ipv4, use_ipv6;
+ int full_log = 1;
+ char *host = SSL_HOST_NAME;
+ char *cert_file = NULL, *key_file = NULL, *chain_file = NULL;
+@@ -709,7 +714,11 @@
+ #endif
+ char *sess_in = NULL;
+ char *sess_out = NULL;
+- struct sockaddr peer;
++#if OPENSSL_USE_IPV6
++ struct sockaddr_storage peer;
++#else
++ struct sockaddr_in peer;
++#endif
+ int peerlen = sizeof(peer);
+ int fallback_scsv = 0;
+ int enable_timeouts = 0;
+@@ -737,6 +746,12 @@
+
+ meth = SSLv23_client_method();
+
++ use_ipv4 = 1;
++#if OPENSSL_USE_IPV6
++ use_ipv6 = 1;
++#else
++ use_ipv6 = 0;
++#endif
+ apps_startup();
+ c_Pause = 0;
+ c_quiet = 0;
+@@ -1096,6 +1111,16 @@
+ jpake_secret = *++argv;
+ }
+ #endif
++ else if (strcmp(*argv,"-4") == 0) {
++ use_ipv4 = 1;
++ use_ipv6 = 0;
++ }
++#if OPENSSL_USE_IPV6
++ else if (strcmp(*argv,"-6") == 0) {
++ use_ipv4 = 0;
++ use_ipv6 = 1;
++ }
++#endif
+ #ifndef OPENSSL_NO_SRTP
+ else if (strcmp(*argv, "-use_srtp") == 0) {
+ if (--argc < 1)
+@@ -1421,7 +1446,7 @@
+
+ re_start:
+
+- if (init_client(&s, host, port, socket_type) == 0) {
++ if (init_client(&s, host, port, socket_type, use_ipv4, use_ipv6) == 0) {
+ BIO_printf(bio_err, "connect:errno=%d\n", get_last_socket_error());
+ SHUTDOWN(s);
+ goto end;
+@@ -1444,7 +1469,7 @@
+ if (socket_type == SOCK_DGRAM) {
+
+ sbio = BIO_new_dgram(s, BIO_NOCLOSE);
+- if (getsockname(s, &peer, (void *)&peerlen) < 0) {
++ if (getsockname(s, (struct sockaddr *)&peer, (void *)&peerlen) < 0) {
+ BIO_printf(bio_err, "getsockname:errno=%d\n",
+ get_last_socket_error());
+ SHUTDOWN(s);
+--- openssl-1.0.2/apps/s_server.c
++++ openssl-1.0.2/apps/s_server.c
+@@ -643,6 +643,10 @@
+ BIO_printf(bio_err,
+ " -alpn arg - set the advertised protocols for the ALPN extension (comma-separated list)\n");
+ #endif
++ BIO_printf(bio_err, " -4 - use IPv4 only\n");
++#if OPENSSL_USE_IPV6
++ BIO_printf(bio_err, " -6 - use IPv6 only\n");
++#endif
+ BIO_printf(bio_err,
+ " -keymatexport label - Export keying material using label\n");
+ BIO_printf(bio_err,
+@@ -1070,6 +1074,7 @@
+ int state = 0;
+ const SSL_METHOD *meth = NULL;
+ int socket_type = SOCK_STREAM;
++ int use_ipv4, use_ipv6;
+ ENGINE *e = NULL;
+ char *inrand = NULL;
+ int s_cert_format = FORMAT_PEM, s_key_format = FORMAT_PEM;
+@@ -1111,6 +1116,12 @@
+
+ meth = SSLv23_server_method();
+
++ use_ipv4 = 1;
++#if OPENSSL_USE_IPV6
++ use_ipv6 = 1;
++#else
++ use_ipv6 = 0;
++#endif
+ local_argc = argc;
+ local_argv = argv;
+
+@@ -1503,6 +1514,16 @@
+ jpake_secret = *(++argv);
+ }
+ #endif
++ else if (strcmp(*argv,"-4") == 0) {
++ use_ipv4 = 1;
++ use_ipv6 = 0;
++ }
++#if OPENSSL_USE_IPV6
++ else if (strcmp(*argv,"-6") == 0) {
++ use_ipv4 = 0;
++ use_ipv6 = 1;
++ }
++#endif
+ #ifndef OPENSSL_NO_SRTP
+ else if (strcmp(*argv, "-use_srtp") == 0) {
+ if (--argc < 1)
+@@ -2023,13 +2044,13 @@
+ (void)BIO_flush(bio_s_out);
+ if (rev)
+ do_server(port, socket_type, &accept_socket, rev_body, context,
+- naccept);
++ naccept, use_ipv4, use_ipv6);
+ else if (www)
+ do_server(port, socket_type, &accept_socket, www_body, context,
+- naccept);
++ naccept, use_ipv4, use_ipv6);
+ else
+ do_server(port, socket_type, &accept_socket, sv_body, context,
+- naccept);
++ naccept, use_ipv4, use_ipv6);
+ print_stats(bio_s_out, ctx);
+ ret = 0;
+ end:
+--- openssl-1.0.2/apps/s_socket.c
++++ openssl-1.0.2/apps/s_socket.c
+@@ -101,16 +101,16 @@
+ # include "netdb.h"
+ # endif
+
+-static struct hostent *GetHostByName(char *name);
++static struct hostent *GetHostByName(char *name, int domain);
+ # if defined(OPENSSL_SYS_WINDOWS) || (defined(OPENSSL_SYS_NETWARE) && !defined(NETWARE_BSDSOCK))
+ static void ssl_sock_cleanup(void);
+ # endif
+ static int ssl_sock_init(void);
+-static int init_client_ip(int *sock, unsigned char ip[4], int port, int type);
+-static int init_server(int *sock, int port, int type);
+-static int init_server_long(int *sock, int port, char *ip, int type);
++static int init_client_ip(int *sock, unsigned char *ip, int port, int type, int domain);
++static int init_server(int *sock, int port, int type, int use_ipv4, int use_ipv6);
++static int init_server_long(int *sock, int port, char *ip, int type, int use_ipv4, int use_ipv6);
+ static int do_accept(int acc_sock, int *sock, char **host);
+-static int host_ip(char *str, unsigned char ip[4]);
++static int host_ip(char *str, unsigned char *ip, int domain);
+
+ # ifdef OPENSSL_SYS_WIN16
+ # define SOCKET_PROTOCOL 0 /* more microsoft stupidity */
+@@ -231,38 +231,68 @@
+ return (1);
+ }
+
+-int init_client(int *sock, char *host, int port, int type)
++int init_client(int *sock, char *host, int port, int type, int use_ipv4, int use_ipv6)
+ {
++# if OPENSSL_USE_IPV6
++ unsigned char ip[16];
++# else
+ unsigned char ip[4];
++# endif
+
+- memset(ip, '\0', sizeof ip);
+- if (!host_ip(host, &(ip[0])))
+- 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)
+-{
+- unsigned long addr;
++ if (use_ipv4)
++ if (host_ip(host, ip, AF_INET))
++ return(init_client_ip(sock, ip, port, type, AF_INET));
++# if OPENSSL_USE_IPV6
++ if (use_ipv6)
++ if (host_ip(host, ip, AF_INET6))
++ return(init_client_ip(sock, ip, port, type, AF_INET6));
++# endif
++ return 0;
++}
++
++static int init_client_ip(int *sock, unsigned char ip[4], int port, int type, int domain)
++{
++# if OPENSSL_USE_IPV6
++ struct sockaddr_storage them;
++ struct sockaddr_in *them_in = (struct sockaddr_in *)&them;
++ struct sockaddr_in6 *them_in6 = (struct sockaddr_in6 *)&them;
++# else
+ struct sockaddr_in them;
++ struct sockaddr_in *them_in = &them;
++# endif
++ socklen_t addr_len;
+ int s, i;
+
+ if (!ssl_sock_init())
+ return (0);
+
+ memset((char *)&them, 0, sizeof(them));
+- them.sin_family = AF_INET;
+- them.sin_port = htons((unsigned short)port);
+- addr = (unsigned long)
+- ((unsigned long)ip[0] << 24L) |
+- ((unsigned long)ip[1] << 16L) |
+- ((unsigned long)ip[2] << 8L) | ((unsigned long)ip[3]);
+- them.sin_addr.s_addr = htonl(addr);
++ if (domain == AF_INET) {
++ addr_len = (socklen_t)sizeof(struct sockaddr_in);
++ them_in->sin_family=AF_INET;
++ them_in->sin_port=htons((unsigned short)port);
++# ifndef BIT_FIELD_LIMITS
++ memcpy(&them_in->sin_addr.s_addr, ip, 4);
++# else
++ memcpy(&them_in->sin_addr, ip, 4);
++# endif
++ }
++ else
++# if OPENSSL_USE_IPV6
++ {
++ addr_len = (socklen_t)sizeof(struct sockaddr_in6);
++ them_in6->sin6_family=AF_INET6;
++ them_in6->sin6_port=htons((unsigned short)port);
++ memcpy(&(them_in6->sin6_addr), ip, sizeof(struct in6_addr));
++ }
++# else
++ return(0);
++# endif
+
+ if (type == SOCK_STREAM)
+- s = socket(AF_INET, SOCK_STREAM, SOCKET_PROTOCOL);
++ s = socket(domain, SOCK_STREAM, SOCKET_PROTOCOL);
+ else /* ( type == SOCK_DGRAM) */
+- s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
++ s = socket(domain, SOCK_DGRAM, IPPROTO_UDP);
+
+ if (s == INVALID_SOCKET) {
+ perror("socket");
+@@ -280,7 +310,7 @@
+ }
+ # endif
+
+- if (connect(s, (struct sockaddr *)&them, sizeof(them)) == -1) {
++ if (connect(s, (struct sockaddr *)&them, addr_len) == -1) {
+ closesocket(s);
+ perror("connect");
+ return (0);
+@@ -292,14 +322,14 @@
+ int do_server(int port, int type, int *ret,
+ int (*cb) (char *hostname, int s, int stype,
+ unsigned char *context), unsigned char *context,
+- int naccept)
++ int naccept, int use_ipv4, int use_ipv6)
+ {
+ int sock;
+ char *name = NULL;
+ int accept_socket = 0;
+ int i;
+
+- if (!init_server(&accept_socket, port, type))
++ if (!init_server(&accept_socket, port, type, use_ipv4, use_ipv6))
+ return (0);
+
+ if (ret != NULL) {
+@@ -328,32 +358,41 @@
+ }
+ }
+
+-static int init_server_long(int *sock, int port, char *ip, int type)
++static int init_server_long(int *sock, int port, char *ip, int type, int use_ipv4, int use_ipv6)
+ {
+ int ret = 0;
++ int domain;
++# if OPENSSL_USE_IPV6
++ struct sockaddr_storage server;
++ struct sockaddr_in *server_in = (struct sockaddr_in *)&server;
++ struct sockaddr_in6 *server_in6 = (struct sockaddr_in6 *)&server;
++# else
+ struct sockaddr_in server;
++ struct sockaddr_in *server_in = &server;
++# endif
++ socklen_t addr_len;
+ int s = -1;
+
++ if (!use_ipv4 && !use_ipv6)
++ goto err;
++# if OPENSSL_USE_IPV6
++ /* we are fine here */
++# else
++ if (use_ipv6)
++ goto err;
++# endif
+ if (!ssl_sock_init())
+ return (0);
+
+- memset((char *)&server, 0, sizeof(server));
+- server.sin_family = AF_INET;
+- server.sin_port = htons((unsigned short)port);
+- if (ip == NULL)
+- server.sin_addr.s_addr = INADDR_ANY;
+- else
+-/* Added for T3E, address-of fails on bit field (beckman@acl.lanl.gov) */
+-# ifndef BIT_FIELD_LIMITS
+- memcpy(&server.sin_addr.s_addr, ip, 4);
++#if OPENSSL_USE_IPV6
++ domain = use_ipv6 ? AF_INET6 : AF_INET;
+ # else
+- memcpy(&server.sin_addr, ip, 4);
++ domain = AF_INET;
+ # endif
+-
+ if (type == SOCK_STREAM)
+- s = socket(AF_INET, SOCK_STREAM, SOCKET_PROTOCOL);
+- else /* type == SOCK_DGRAM */
+- s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
++ s=socket(domain, SOCK_STREAM, SOCKET_PROTOCOL);
++ else /* type == SOCK_DGRAM */
++ s=socket(domain, SOCK_DGRAM, IPPROTO_UDP);
+
+ if (s == INVALID_SOCKET)
+ goto err;
+@@ -363,7 +402,42 @@
+ setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (void *)&j, sizeof j);
+ }
+ # endif
+- if (bind(s, (struct sockaddr *)&server, sizeof(server)) == -1) {
++# if OPENSSL_USE_IPV6
++ if ((use_ipv4 == 0) && (use_ipv6 == 1)) {
++ const int on = 1;
++
++ setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY,
++ (const void *) &on, sizeof(int));
++ }
++# endif
++ if (domain == AF_INET) {
++ addr_len = (socklen_t)sizeof(struct sockaddr_in);
++ memset(server_in, 0, sizeof(struct sockaddr_in));
++ server_in->sin_family=AF_INET;
++ server_in->sin_port = htons((unsigned short)port);
++ if (ip == NULL)
++ server_in->sin_addr.s_addr = htonl(INADDR_ANY);
++ else
++/* Added for T3E, address-of fails on bit field (beckman@acl.lanl.gov) */
++# ifndef BIT_FIELD_LIMITS
++ memcpy(&server_in->sin_addr.s_addr, ip, 4);
++# else
++ memcpy(&server_in->sin_addr, ip, 4);
++# endif
++ }
++# if OPENSSL_USE_IPV6
++ else {
++ addr_len = (socklen_t)sizeof(struct sockaddr_in6);
++ memset(server_in6, 0, sizeof(struct sockaddr_in6));
++ server_in6->sin6_family = AF_INET6;
++ server_in6->sin6_port = htons((unsigned short)port);
++ if (ip == NULL)
++ server_in6->sin6_addr = in6addr_any;
++ else
++ memcpy(&server_in6->sin6_addr, ip, sizeof(struct in6_addr));
++ }
++# endif
++ if (bind(s, (struct sockaddr *)&server, addr_len) == -1) {
+ # ifndef OPENSSL_SYS_WINDOWS
+ perror("bind");
+ # endif
+@@ -381,16 +455,23 @@
+ return (ret);
+ }
+
+-static int init_server(int *sock, int port, int type)
++static int init_server(int *sock, int port, int type, int use_ipv4, int use_ipv6)
+ {
+- return (init_server_long(sock, port, NULL, type));
++ return (init_server_long(sock, port, NULL, type, use_ipv4, use_ipv6));
+ }
+
+ static int do_accept(int acc_sock, int *sock, char **host)
+ {
+ int ret;
+ struct hostent *h1, *h2;
+- static struct sockaddr_in from;
++#if OPENSSL_USE_IPV6
++ struct sockaddr_storage from;
++ struct sockaddr_in *from_in = (struct sockaddr_in *)&from;
++ struct sockaddr_in6 *from_in6 = (struct sockaddr_in6 *)&from;
++#else
++ struct sockaddr_in from;
++ struct sockaddr_in *from_in = &from;
++#endif
+ int len;
+ /* struct linger ling; */
+
+@@ -440,14 +521,25 @@
+
+ if (host == NULL)
+ goto end;
++# if OPENSSL_USE_IPV6
++ if (from.ss_family == AF_INET)
++# else
++ if (from.sin_family == AF_INET)
++# endif
+ # ifndef BIT_FIELD_LIMITS
+- /* I should use WSAAsyncGetHostByName() under windows */
+- h1 = gethostbyaddr((char *)&from.sin_addr.s_addr,
+- sizeof(from.sin_addr.s_addr), AF_INET);
++ /* I should use WSAAsyncGetHostByName() under windows */
++ h1 = gethostbyaddr((char *)&from_in->sin_addr.s_addr,
++ sizeof(from_in->sin_addr.s_addr), AF_INET);
+ # else
+- h1 = gethostbyaddr((char *)&from.sin_addr,
+- sizeof(struct in_addr), AF_INET);
++ h1 = gethostbyaddr((char *)&from_in->sin_addr,
++ sizeof(struct in_addr), AF_INET);
++# endif
++# if OPENSSL_USE_IPV6
++ else
++ h1 = gethostbyaddr((char *)&from_in6->sin6_addr,
++ sizeof(struct in6_addr), AF_INET6);
+ # endif
++
+ if (h1 == NULL) {
+ BIO_printf(bio_err, "bad gethostbyaddr\n");
+ *host = NULL;
+@@ -460,14 +552,22 @@
+ }
+ BUF_strlcpy(*host, h1->h_name, strlen(h1->h_name) + 1);
+
+- h2 = GetHostByName(*host);
++# if OPENSSL_USE_IPV6
++ h2=GetHostByName(*host, from.ss_family);
++# else
++ h2=GetHostByName(*host, from.sin_family);
++# endif
+ if (h2 == NULL) {
+ BIO_printf(bio_err, "gethostbyname failure\n");
+ closesocket(ret);
+ return (0);
+ }
+- if (h2->h_addrtype != AF_INET) {
+- BIO_printf(bio_err, "gethostbyname addr is not AF_INET\n");
++# if OPENSSL_USE_IPV6
++ if (h2->h_addrtype != from.ss_family) {
++# else
++ if (h2->h_addrtype != from.sin_family) {
++# endif
++ BIO_printf(bio_err, "gethostbyname addr is not correct\n");
+ closesocket(ret);
+ return (0);
+ }
+@@ -483,14 +583,14 @@
+ char *h, *p;
+
+ h = str;
+- p = strchr(str, ':');
++ p = strrchr(str, ':');
+ if (p == NULL) {
+ BIO_printf(bio_err, "no port defined\n");
+ return (0);
+ }
+ *(p++) = '\0';
+
+- if ((ip != NULL) && !host_ip(str, ip))
++ if ((ip != NULL) && !host_ip(str, ip, AF_INET))
+ goto err;
+ if (host_ptr != NULL)
+ *host_ptr = h;
+@@ -502,44 +602,51 @@
+ return (0);
+ }
+
+-static int host_ip(char *str, unsigned char ip[4])
++static int host_ip(char *str, unsigned char *ip, int domain)
+ {
+ unsigned int in[4];
++ unsigned long l;
+ int i;
+
+- if (sscanf(str, "%u.%u.%u.%u", &(in[0]), &(in[1]), &(in[2]), &(in[3])) ==
+- 4) {
++ if ((domain == AF_INET) && (sscanf(str, "%u.%u.%u.%u", &(in[0]), &(in[1]), &(in[2]), &(in[3])) == 4)) {
+ for (i = 0; i < 4; i++)
+ if (in[i] > 255) {
+ BIO_printf(bio_err, "invalid IP address\n");
+ goto err;
+ }
+- ip[0] = in[0];
+- ip[1] = in[1];
+- ip[2] = in[2];
+- ip[3] = in[3];
+- } else { /* do a gethostbyname */
++ l=htonl((in[0]<<24L)|(in[1]<<16L)|(in[2]<<8L)|in[3]);
++ memcpy(ip, &l, 4);
++ return 1;
++ }
++# if OPENSSL_USE_IPV6
++ else if ((domain == AF_INET6) && (inet_pton(AF_INET6, str, ip) == 1))
++ return 1;
++# endif
++ else { /* do a gethostbyname */
+ struct hostent *he;
+
+ if (!ssl_sock_init())
+ return (0);
+
+- he = GetHostByName(str);
++ he = GetHostByName(str, domain);
+ if (he == NULL) {
+ BIO_printf(bio_err, "gethostbyname failure\n");
+ goto err;
+ }
+ /* cast to short because of win16 winsock definition */
+- if ((short)he->h_addrtype != AF_INET) {
+- BIO_printf(bio_err, "gethostbyname addr is not AF_INET\n");
++ if ((short)he->h_addrtype != domain) {
++ BIO_printf(bio_err, "gethostbyname addr is not correct\n");
+ return (0);
+ }
+- ip[0] = he->h_addr_list[0][0];
+- ip[1] = he->h_addr_list[0][1];
+- ip[2] = he->h_addr_list[0][2];
+- ip[3] = he->h_addr_list[0][3];
++ if (domain == AF_INET)
++ memset(ip, 0, 4);
++# if OPENSSL_USE_IPV6
++ else
++ memset(ip, 0, 16);
++# endif
++ memcpy(ip, he->h_addr_list[0], he->h_length);
++ return 1;
+ }
+- return (1);
+ err:
+ return (0);
+ }
+@@ -573,7 +680,7 @@
+ static unsigned long ghbn_hits = 0L;
+ static unsigned long ghbn_miss = 0L;
+
+-static struct hostent *GetHostByName(char *name)
++static struct hostent *GetHostByName(char *name, int domain)
+ {
+ struct hostent *ret;
+ int i, lowi = 0;
+@@ -585,13 +692,18 @@
+ lowi = i;
+ }
+ if (ghbn_cache[i].order > 0) {
+- if (strncmp(name, ghbn_cache[i].name, 128) == 0)
++ if ((strncmp(name, ghbn_cache[i].name, 128) == 0) && (ghbn_cache[i].ent.h_addrtype == domain))
+ break;
+ }
+ }
+ if (i == GHBN_NUM) { /* no hit */
+ ghbn_miss++;
+- ret = gethostbyname(name);
++ if (domain == AF_INET)
++ ret = gethostbyname(name);
++# if OPENSSL_USE_IPV6
++ else
++ ret = gethostbyname2(name, AF_INET6);
++# endif
+ if (ret == NULL)
+ return (NULL);
+ /* else add to cache */
diff --git a/dev-libs/openssl/files/openssl-1.0.2a-parallel-install-dirs.patch b/dev-libs/openssl/files/openssl-1.0.2a-parallel-install-dirs.patch
new file mode 100644
index 0000000..0198818
--- /dev/null
+++ b/dev-libs/openssl/files/openssl-1.0.2a-parallel-install-dirs.patch
@@ -0,0 +1,64 @@
+https://rt.openssl.org/Ticket/Display.html?id=3736&user=guest&pass=guest
+
+From aba899f2eca21e11e5e9797bf8258e7265dea9f5 Mon Sep 17 00:00:00 2001
+From: Mike Frysinger <vapier@gentoo.org>
+Date: Sun, 8 Mar 2015 01:32:01 -0500
+Subject: [PATCH] fix parallel install with dir creation
+
+The mkdir-p.pl does not handle parallel creation of directories.
+This comes up when the install_sw and install_docs rules run and
+both call mkdir-p.pl on sibling directory trees.
+
+Instead, lets create a single install_dirs rule that makes all of
+the dirs we need, and have these two install steps depend on that.
+---
+ Makefile.org | 17 +++++++++--------
+ 1 file changed, 9 insertions(+), 8 deletions(-)
+
+diff --git a/Makefile.org b/Makefile.org
+index a6d9471..78e6143 100644
+--- a/Makefile.org
++++ b/Makefile.org
+@@ -536,9 +536,9 @@
+ dist_pem_h:
+ (cd crypto/pem; $(MAKE) -e $(BUILDENV) pem.h; $(MAKE) clean)
+
+-install: all install_docs install_sw
++install: install_docs install_sw
+
+-install_sw:
++install_dirs:
+ @$(PERL) $(TOP)/util/mkdir-p.pl $(INSTALL_PREFIX)$(INSTALLTOP)/bin \
+ $(INSTALL_PREFIX)$(INSTALLTOP)/$(LIBDIR) \
+ $(INSTALL_PREFIX)$(INSTALLTOP)/$(LIBDIR)/engines \
+@@ -547,6 +547,13 @@
+ $(INSTALL_PREFIX)$(OPENSSLDIR)/misc \
+ $(INSTALL_PREFIX)$(OPENSSLDIR)/certs \
+ $(INSTALL_PREFIX)$(OPENSSLDIR)/private
++ @$(PERL) $(TOP)/util/mkdir-p.pl \
++ $(INSTALL_PREFIX)$(MANDIR)/man1 \
++ $(INSTALL_PREFIX)$(MANDIR)/man3 \
++ $(INSTALL_PREFIX)$(MANDIR)/man5 \
++ $(INSTALL_PREFIX)$(MANDIR)/man7
++
++install_sw: install_dirs
+ @set -e; headerlist="$(EXHEADER)"; for i in $$headerlist;\
+ do \
+ (cp $$i $(INSTALL_PREFIX)$(INSTALLTOP)/include/openssl/$$i; \
+@@ -636,12 +643,7 @@
+ done; \
+ done
+
+-install_docs:
+- @$(PERL) $(TOP)/util/mkdir-p.pl \
+- $(INSTALL_PREFIX)$(MANDIR)/man1 \
+- $(INSTALL_PREFIX)$(MANDIR)/man3 \
+- $(INSTALL_PREFIX)$(MANDIR)/man5 \
+- $(INSTALL_PREFIX)$(MANDIR)/man7
++install_docs: install_dirs
+ @pod2man="`cd ./util; ./pod2mantest $(PERL)`"; \
+ here="`pwd`"; \
+ filecase=; \
+--
+2.3.4
+
diff --git a/dev-libs/openssl/files/openssl-1.0.2a-parallel-obj-headers.patch b/dev-libs/openssl/files/openssl-1.0.2a-parallel-obj-headers.patch
new file mode 100644
index 0000000..a7d6f4e
--- /dev/null
+++ b/dev-libs/openssl/files/openssl-1.0.2a-parallel-obj-headers.patch
@@ -0,0 +1,37 @@
+https://rt.openssl.org/Ticket/Display.html?id=3737&user=guest&pass=guest
+
+From ce279d4361e07e9af9ceca8a6e326e661758ad53 Mon Sep 17 00:00:00 2001
+From: Mike Frysinger <vapier@gentoo.org>
+Date: Sun, 8 Mar 2015 01:34:48 -0500
+Subject: [PATCH] fix parallel generation of obj headers
+
+The current code has dummy sleep/touch commands to try and work
+around the parallel issue, but that is obviously racy. Instead
+lets force one of the files to depend on the other so we know
+they'll never run in parallel.
+---
+ crypto/objects/Makefile | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/crypto/objects/Makefile b/crypto/objects/Makefile
+index ad2db1e..7d32504 100644
+--- a/crypto/objects/Makefile
++++ b/crypto/objects/Makefile
+@@ -44,11 +44,11 @@
+ # objects.pl both reads and writes obj_mac.num
+ obj_mac.h: objects.pl objects.txt obj_mac.num
+ $(PERL) objects.pl objects.txt obj_mac.num obj_mac.h
+- @sleep 1; touch obj_mac.h; sleep 1
+
+-obj_xref.h: objxref.pl obj_xref.txt obj_mac.num
++# This doesn't really need obj_mac.h, but since that rule reads & writes
++# obj_mac.num, we can't run in parallel with it.
++obj_xref.h: objxref.pl obj_xref.txt obj_mac.num obj_mac.h
+ $(PERL) objxref.pl obj_mac.num obj_xref.txt > obj_xref.h
+- @sleep 1; touch obj_xref.h; sleep 1
+
+ files:
+ $(PERL) $(TOP)/util/files.pl Makefile >> $(TOP)/MINFO
+--
+2.3.4
+
diff --git a/dev-libs/openssl/files/openssl-1.0.2a-parallel-symlinking.patch b/dev-libs/openssl/files/openssl-1.0.2a-parallel-symlinking.patch
new file mode 100644
index 0000000..f2be696
--- /dev/null
+++ b/dev-libs/openssl/files/openssl-1.0.2a-parallel-symlinking.patch
@@ -0,0 +1,63 @@
+https://rt.openssl.org/Ticket/Display.html?id=3780&user=guest&pass=guest
+
+From cc81af135bda47eaa6956a0329cbbc55bf993ac1 Mon Sep 17 00:00:00 2001
+From: Mike Frysinger <vapier@gentoo.org>
+Date: Fri, 3 Apr 2015 01:16:23 -0400
+Subject: [PATCH] fix race when symlink shareds libs
+
+When the crypto/ssl targets attempt to build their shared libs, they run:
+ cd ..; make libcrypto.so.1.0.0
+The top level Makefile in turn runs the build-shared target for that lib.
+
+The build-shared target depends on both do_$(SHLIB_TARGET) & link-shared.
+When building in parallel, make is allowed to run both of these. They
+both run Makefile.shared for their respective targets:
+do_$(SHLIB_TARGET) ->
+ link_a.linux-shared ->
+ link_a.gnu ->
+ ...; $(LINK_SO_A) ->
+ $(LINK_SO) ->
+ $(SYMLINK_SO)
+link-shared ->
+ symlink.linux-shared ->
+ symlink.gnu ->
+ ...; $(SYMLINK_SO)
+
+The shell code for SYMLINK_SO attempts to do a [ -e lib ] check, but fails
+basic TOCTOU semantics. Depending on the load, that means two processes
+will run the sequence:
+ rm -f libcrypto.so
+ ln -s libcrypto.so.1.0.0 libcrypto.so
+
+Which obviously fails:
+ ln: failed to create symbolic link 'libcrypto.so': File exists
+
+Since we know do_$(SHLIB_TARGET) will create the symlink for us, don't
+bother depending on link-shared at all in the top level Makefile when
+building things.
+
+Reported-by: Martin von Gagern <Martin.vGagern@gmx.net>
+URL: https://bugs.gentoo.org/545028
+---
+ Makefile.org | 5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+diff --git a/Makefile.org b/Makefile.org
+index 890bfe4..576c60e 100644
+--- a/Makefile.org
++++ b/Makefile.org
+@@ -350,7 +350,10 @@ link-shared:
+ libs="$$libs -l$$i"; \
+ done
+
+-build-shared: do_$(SHLIB_TARGET) link-shared
++# The link target in Makefile.shared will create the symlink for us, so no need
++# to call link-shared directly. Doing so will cause races with two processes
++# trying to symlink the lib.
++build-shared: do_$(SHLIB_TARGET)
+
+ do_$(SHLIB_TARGET):
+ @ set -e; libs='-L. $(SHLIBDEPS)'; for i in $(SHLIBDIRS); do \
+--
+2.3.4
+
diff --git a/dev-libs/openssl/files/openssl-1.0.2a-x32-asm.patch b/dev-libs/openssl/files/openssl-1.0.2a-x32-asm.patch
new file mode 100644
index 0000000..3a005c9
--- /dev/null
+++ b/dev-libs/openssl/files/openssl-1.0.2a-x32-asm.patch
@@ -0,0 +1,43 @@
+https://rt.openssl.org/Ticket/Display.html?id=3759&user=guest&pass=guest
+
+From 6257d59b3a68d2feb9d64317a1c556dc3813ee61 Mon Sep 17 00:00:00 2001
+From: Mike Frysinger <vapier@gentoo.org>
+Date: Sat, 21 Mar 2015 06:01:25 -0400
+Subject: [PATCH] crypto: use bigint in x86-64 perl
+
+When building on x32 systems where the default type is 32bit, make sure
+we can transparently represent 64bit integers. Otherwise we end up with
+build errors like:
+/usr/bin/perl asm/ghash-x86_64.pl elf > ghash-x86_64.s
+Integer overflow in hexadecimal number at asm/../../perlasm/x86_64-xlate.pl line 201, <> line 890.
+...
+ghash-x86_64.s: Assembler messages:
+ghash-x86_64.s:890: Error: junk '.15473355479995e+19' after expression
+
+We don't enable this globally as there are some cases where we'd get
+32bit values interpreted as unsigned when we need them as signed.
+
+Reported-by: Bertrand Jacquin <bertrand@jacquin.bzh>
+URL: https://bugs.gentoo.org/542618
+---
+ crypto/perlasm/x86_64-xlate.pl | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/crypto/perlasm/x86_64-xlate.pl b/crypto/perlasm/x86_64-xlate.pl
+index aae8288..0bf9774 100755
+--- a/crypto/perlasm/x86_64-xlate.pl
++++ b/crypto/perlasm/x86_64-xlate.pl
+@@ -195,6 +195,10 @@ my %globals;
+ sub out {
+ my $self = shift;
+
++ # When building on x32 ABIs, the expanded hex value might be too
++ # big to fit into 32bits. Enable transparent 64bit support here
++ # so we can safely print it out.
++ use bigint;
+ if ($gas) {
+ # Solaris /usr/ccs/bin/as can't handle multiplications
+ # in $self->{value}
+--
+2.3.3
+
diff --git a/dev-libs/openssl/files/openssl-1.0.2e-chacha20_poly1305_cf.patch b/dev-libs/openssl/files/openssl-1.0.2e-chacha20_poly1305_cf.patch
new file mode 100644
index 0000000..4949c40
--- /dev/null
+++ b/dev-libs/openssl/files/openssl-1.0.2e-chacha20_poly1305_cf.patch
@@ -0,0 +1,4462 @@
+From 68bc18b82f7437373f9c301dce8fa811490e9567 Mon Sep 17 00:00:00 2001
+From: Vlad Krasnov <vlad@cloudflare.com>
+Date: Thu, 17 Sep 2015 17:36:53 -0700
+Subject: [PATCH] CHACHA20-POLY1305 Draft 1
+
+Rebase of the original patch on top of OpenSSL 1.0.2 stable as of September 19,
+2015
+---
+ Configure | 50 +-
+ Makefile.org | 4 +-
+ apps/speed.c | 34 +-
+ crypto/chacha20poly1305/Makefile | 92 +++
+ crypto/chacha20poly1305/asm/chacha20_avx.pl | 388 +++++++++++
+ crypto/chacha20poly1305/asm/chacha20_avx2.pl | 424 +++++++++++++
+ crypto/chacha20poly1305/asm/poly1305_avx.pl | 717 +++++++++++++++++++++
+ crypto/chacha20poly1305/asm/poly1305_avx2.pl | 918 +++++++++++++++++++++++++++
+ crypto/chacha20poly1305/chacha20.c | 157 +++++
+ crypto/chacha20poly1305/chacha20poly1305.h | 63 ++
+ crypto/chacha20poly1305/chapolytest.c | 287 +++++++++
+ crypto/chacha20poly1305/poly1305.c | 285 +++++++++
+ crypto/cryptlib.c | 14 +-
+ crypto/crypto.h | 2 +-
+ crypto/evp/Makefile | 7 +-
+ crypto/evp/e_chacha20poly1305.c | 323 ++++++++++
+ crypto/evp/evp.h | 3 +
+ crypto/objects/obj_dat.h | 10 +-
+ crypto/objects/obj_mac.h | 4 +
+ ssl/s3_lib.c | 62 +-
+ ssl/ssl.h | 1 +
+ ssl/ssl_algs.c | 4 +
+ ssl/ssl_ciph.c | 15 +-
+ ssl/ssl_locl.h | 1 +
+ ssl/tls1.h | 10 +
+ test/Makefile | 17 +-
+ 26 files changed, 3845 insertions(+), 47 deletions(-)
+ create mode 100644 crypto/chacha20poly1305/Makefile
+ create mode 100644 crypto/chacha20poly1305/asm/chacha20_avx.pl
+ create mode 100644 crypto/chacha20poly1305/asm/chacha20_avx2.pl
+ create mode 100644 crypto/chacha20poly1305/asm/poly1305_avx.pl
+ create mode 100644 crypto/chacha20poly1305/asm/poly1305_avx2.pl
+ create mode 100644 crypto/chacha20poly1305/chacha20.c
+ create mode 100644 crypto/chacha20poly1305/chacha20poly1305.h
+ create mode 100644 crypto/chacha20poly1305/chapolytest.c
+ create mode 100644 crypto/chacha20poly1305/poly1305.c
+ create mode 100644 crypto/evp/e_chacha20poly1305.c
+
+diff --git a/Configure b/Configure
+index d99eed7..1a7f5f3 100755
+--- a/Configure
++++ b/Configure
+@@ -143,25 +143,25 @@ my $tlib="-lnsl -lsocket";
+ my $bits1="THIRTY_TWO_BIT ";
+ my $bits2="SIXTY_FOUR_BIT ";
+
+-my $x86_asm="x86cpuid.o:bn-586.o co-586.o x86-mont.o x86-gf2m.o::des-586.o crypt586.o:aes-586.o vpaes-x86.o aesni-x86.o:bf-586.o:md5-586.o:sha1-586.o sha256-586.o sha512-586.o:cast-586.o:rc4-586.o:rmd-586.o:rc5-586.o:wp_block.o wp-mmx.o:cmll-x86.o:ghash-x86.o:";
++my $x86_asm="x86cpuid.o:bn-586.o co-586.o x86-mont.o x86-gf2m.o::des-586.o crypt586.o:aes-586.o vpaes-x86.o aesni-x86.o:bf-586.o:md5-586.o:sha1-586.o sha256-586.o sha512-586.o:cast-586.o:rc4-586.o:rmd-586.o:rc5-586.o:wp_block.o wp-mmx.o:cmll-x86.o:ghash-x86.o::";
+
+ my $x86_elf_asm="$x86_asm:elf";
+
+-my $x86_64_asm="x86_64cpuid.o:x86_64-gcc.o x86_64-mont.o x86_64-mont5.o x86_64-gf2m.o rsaz_exp.o rsaz-x86_64.o rsaz-avx2.o:ecp_nistz256.o ecp_nistz256-x86_64.o::aes-x86_64.o vpaes-x86_64.o bsaes-x86_64.o aesni-x86_64.o aesni-sha1-x86_64.o aesni-sha256-x86_64.o aesni-mb-x86_64.o::md5-x86_64.o:sha1-x86_64.o sha256-x86_64.o sha512-x86_64.o sha1-mb-x86_64.o sha256-mb-x86_64.o::rc4-x86_64.o rc4-md5-x86_64.o:::wp-x86_64.o:cmll-x86_64.o cmll_misc.o:ghash-x86_64.o aesni-gcm-x86_64.o:";
+-my $ia64_asm="ia64cpuid.o:bn-ia64.o ia64-mont.o:::aes_core.o aes_cbc.o aes-ia64.o::md5-ia64.o:sha1-ia64.o sha256-ia64.o sha512-ia64.o::rc4-ia64.o rc4_skey.o:::::ghash-ia64.o::void";
+-my $sparcv9_asm="sparcv9cap.o sparccpuid.o:bn-sparcv9.o sparcv9-mont.o sparcv9a-mont.o vis3-mont.o sparct4-mont.o sparcv9-gf2m.o::des_enc-sparc.o fcrypt_b.o dest4-sparcv9.o:aes_core.o aes_cbc.o aes-sparcv9.o aest4-sparcv9.o::md5-sparcv9.o:sha1-sparcv9.o sha256-sparcv9.o sha512-sparcv9.o::::::camellia.o cmll_misc.o cmll_cbc.o cmllt4-sparcv9.o:ghash-sparcv9.o::void";
+-my $sparcv8_asm=":sparcv8.o::des_enc-sparc.o fcrypt_b.o:::::::::::::void";
+-my $alpha_asm="alphacpuid.o:bn_asm.o alpha-mont.o::::::sha1-alpha.o:::::::ghash-alpha.o::void";
+-my $mips64_asm=":bn-mips.o mips-mont.o:::aes_cbc.o aes-mips.o:::sha1-mips.o sha256-mips.o sha512-mips.o::::::::";
++my $x86_64_asm="x86_64cpuid.o:x86_64-gcc.o x86_64-mont.o x86_64-mont5.o x86_64-gf2m.o rsaz_exp.o rsaz-x86_64.o rsaz-avx2.o:ecp_nistz256.o ecp_nistz256-x86_64.o::aes-x86_64.o vpaes-x86_64.o bsaes-x86_64.o aesni-x86_64.o aesni-sha1-x86_64.o aesni-sha256-x86_64.o aesni-mb-x86_64.o::md5-x86_64.o:sha1-x86_64.o sha256-x86_64.o sha512-x86_64.o sha1-mb-x86_64.o sha256-mb-x86_64.o::rc4-x86_64.o rc4-md5-x86_64.o:::wp-x86_64.o:cmll-x86_64.o cmll_misc.o:ghash-x86_64.o aesni-gcm-x86_64.o::chacha20_avx.o poly1305_avx.o chacha20_avx2.o poly1305_avx2.o";
++my $ia64_asm="ia64cpuid.o:bn-ia64.o ia64-mont.o:::aes_core.o aes_cbc.o aes-ia64.o::md5-ia64.o:sha1-ia64.o sha256-ia64.o sha512-ia64.o::rc4-ia64.o rc4_skey.o:::::ghash-ia64.o:::void";
++my $sparcv9_asm="sparcv9cap.o sparccpuid.o:bn-sparcv9.o sparcv9-mont.o sparcv9a-mont.o vis3-mont.o sparct4-mont.o sparcv9-gf2m.o::des_enc-sparc.o fcrypt_b.o dest4-sparcv9.o:aes_core.o aes_cbc.o aes-sparcv9.o aest4-sparcv9.o::md5-sparcv9.o:sha1-sparcv9.o sha256-sparcv9.o sha512-sparcv9.o::::::camellia.o cmll_misc.o cmll_cbc.o cmllt4-sparcv9.o:ghash-sparcv9.o:::void";
++my $sparcv8_asm=":sparcv8.o::des_enc-sparc.o fcrypt_b.o::::::::::::::void";
++my $alpha_asm="alphacpuid.o:bn_asm.o alpha-mont.o::::::sha1-alpha.o:::::::ghash-alpha.o:::void";
++my $mips64_asm=":bn-mips.o mips-mont.o:::aes_cbc.o aes-mips.o:::sha1-mips.o sha256-mips.o sha512-mips.o:::::::::";
+ my $mips32_asm=$mips64_asm; $mips32_asm =~ s/\s*sha512\-mips\.o//;
+-my $s390x_asm="s390xcap.o s390xcpuid.o:bn-s390x.o s390x-mont.o s390x-gf2m.o:::aes-s390x.o aes-ctr.o aes-xts.o:::sha1-s390x.o sha256-s390x.o sha512-s390x.o::rc4-s390x.o:::::ghash-s390x.o:";
+-my $armv4_asm="armcap.o armv4cpuid.o:bn_asm.o armv4-mont.o armv4-gf2m.o:::aes_cbc.o aes-armv4.o bsaes-armv7.o aesv8-armx.o:::sha1-armv4-large.o sha256-armv4.o sha512-armv4.o:::::::ghash-armv4.o ghashv8-armx.o::void";
+-my $aarch64_asm="armcap.o arm64cpuid.o mem_clr.o::::aes_core.o aes_cbc.o aesv8-armx.o:::sha1-armv8.o sha256-armv8.o sha512-armv8.o:::::::ghashv8-armx.o:";
+-my $parisc11_asm="pariscid.o:bn_asm.o parisc-mont.o:::aes_core.o aes_cbc.o aes-parisc.o:::sha1-parisc.o sha256-parisc.o sha512-parisc.o::rc4-parisc.o:::::ghash-parisc.o::32";
+-my $parisc20_asm="pariscid.o:pa-risc2W.o parisc-mont.o:::aes_core.o aes_cbc.o aes-parisc.o:::sha1-parisc.o sha256-parisc.o sha512-parisc.o::rc4-parisc.o:::::ghash-parisc.o::64";
+-my $ppc64_asm="ppccpuid.o ppccap.o:bn-ppc.o ppc-mont.o ppc64-mont.o:::aes_core.o aes_cbc.o aes-ppc.o vpaes-ppc.o aesp8-ppc.o:::sha1-ppc.o sha256-ppc.o sha512-ppc.o sha256p8-ppc.o sha512p8-ppc.o:::::::ghashp8-ppc.o:";
++my $s390x_asm="s390xcap.o s390xcpuid.o:bn-s390x.o s390x-mont.o s390x-gf2m.o:::aes-s390x.o aes-ctr.o aes-xts.o:::sha1-s390x.o sha256-s390x.o sha512-s390x.o::rc4-s390x.o:::::ghash-s390x.o::";
++my $armv4_asm="armcap.o armv4cpuid.o:bn_asm.o armv4-mont.o armv4-gf2m.o:::aes_cbc.o aes-armv4.o bsaes-armv7.o aesv8-armx.o:::sha1-armv4-large.o sha256-armv4.o sha512-armv4.o:::::::ghash-armv4.o ghashv8-armx.o:::void";
++my $aarch64_asm="armcap.o arm64cpuid.o mem_clr.o::::aes_core.o aes_cbc.o aesv8-armx.o:::sha1-armv8.o sha256-armv8.o sha512-armv8.o:::::::ghashv8-armx.o::";
++my $parisc11_asm="pariscid.o:bn_asm.o parisc-mont.o:::aes_core.o aes_cbc.o aes-parisc.o:::sha1-parisc.o sha256-parisc.o sha512-parisc.o::rc4-parisc.o:::::ghash-parisc.o:::32";
++my $parisc20_asm="pariscid.o:pa-risc2W.o parisc-mont.o:::aes_core.o aes_cbc.o aes-parisc.o:::sha1-parisc.o sha256-parisc.o sha512-parisc.o::rc4-parisc.o:::::ghash-parisc.o:::64";
++my $ppc64_asm="ppccpuid.o ppccap.o:bn-ppc.o ppc-mont.o ppc64-mont.o:::aes_core.o aes_cbc.o aes-ppc.o vpaes-ppc.o aesp8-ppc.o:::sha1-ppc.o sha256-ppc.o sha512-ppc.o sha256p8-ppc.o sha512p8-ppc.o:::::::ghashp8-ppc.o::";
+ my $ppc32_asm=$ppc64_asm;
+-my $no_asm="::::::::::::::::void";
++my $no_asm=":::::::::::::::::void";
+
+ # As for $BSDthreads. Idea is to maintain "collective" set of flags,
+ # which would cover all BSD flavors. -pthread applies to them all,
+@@ -706,6 +706,7 @@ my $idx_wp_obj = $idx++;
+ my $idx_cmll_obj = $idx++;
+ my $idx_modes_obj = $idx++;
+ my $idx_engines_obj = $idx++;
++my $idx_chapoly_obj = $idx++;
+ my $idx_perlasm_scheme = $idx++;
+ my $idx_dso_scheme = $idx++;
+ my $idx_shared_target = $idx++;
+@@ -748,6 +749,7 @@ my $bf ="crypto/bf/bf_locl.h";
+ my $bn_asm ="bn_asm.o";
+ my $des_enc="des_enc.o fcrypt_b.o";
+ my $aes_enc="aes_core.o aes_cbc.o";
++my $chapoly_enc="";
+ my $bf_enc ="bf_enc.o";
+ my $cast_enc="c_enc.o";
+ my $rc4_enc="rc4_enc.o rc4_skey.o";
+@@ -1206,7 +1208,7 @@ $openssldir=$prefix . "/" . $openssldir if $openssldir !~ /(^\/|^[a-zA-Z]:[\\\/]
+
+ print "IsMK1MF=$IsMK1MF\n";
+
+-my @fields = split(/\s*:\s*/,$table{$target} . ":" x 30 , -1);
++my @fields = split(/\s*:\s*/,$table{$target} . ":" x 31 , -1);
+ my $cc = $fields[$idx_cc];
+ # Allow environment CC to override compiler...
+ if($ENV{CC}) {
+@@ -1235,6 +1237,7 @@ my $wp_obj = $fields[$idx_wp_obj];
+ my $cmll_obj = $fields[$idx_cmll_obj];
+ my $modes_obj = $fields[$idx_modes_obj];
+ my $engines_obj = $fields[$idx_engines_obj];
++my $chapoly_obj = $fields[$idx_chapoly_obj];
+ my $perlasm_scheme = $fields[$idx_perlasm_scheme];
+ my $dso_scheme = $fields[$idx_dso_scheme];
+ my $shared_target = $fields[$idx_shared_target];
+@@ -1401,7 +1404,7 @@ if ($no_asm)
+ {
+ $cpuid_obj=$bn_obj=$ec_obj=
+ $des_obj=$aes_obj=$bf_obj=$cast_obj=$rc4_obj=$rc5_obj=$cmll_obj=
+- $modes_obj=$sha1_obj=$md5_obj=$rmd160_obj=$wp_obj=$engines_obj="";
++ $modes_obj=$sha1_obj=$md5_obj=$rmd160_obj=$wp_obj=$engines_obj=$chapoly_obj="";
+ }
+
+ if (!$no_shared)
+@@ -1554,6 +1557,14 @@ $bf_obj=$bf_enc unless ($bf_obj =~ /\.o$/);
+ $cast_obj=$cast_enc unless ($cast_obj =~ /\.o$/);
+ $rc4_obj=$rc4_enc unless ($rc4_obj =~ /\.o$/);
+ $rc5_obj=$rc5_enc unless ($rc5_obj =~ /\.o$/);
++if ($chapoly_obj =~ /\.o$/)
++ {
++ $cflags.=" -DCHAPOLY_x86_64_ASM";
++ }
++else
++ {
++ $chapoly_obj=$chapoly_enc;
++ }
+ if ($sha1_obj =~ /\.o$/)
+ {
+ # $sha1_obj=$sha1_enc;
+@@ -1733,7 +1744,8 @@ while (<IN>)
+ s/^RMD160_ASM_OBJ=.*$/RMD160_ASM_OBJ= $rmd160_obj/;
+ s/^WP_ASM_OBJ=.*$/WP_ASM_OBJ= $wp_obj/;
+ s/^CMLL_ENC=.*$/CMLL_ENC= $cmll_obj/;
+- s/^MODES_ASM_OBJ.=*$/MODES_ASM_OBJ= $modes_obj/;
++ s/^MODES_ASM_OBJ.=*$/MODES_ASM_OBJ= $modes_obj/;
++ s/^CHAPOLY_ENC=.*$/CHAPOLY_ENC= $chapoly_obj/;
+ s/^ENGINES_ASM_OBJ.=*$/ENGINES_ASM_OBJ= $engines_obj/;
+ s/^PERLASM_SCHEME=.*$/PERLASM_SCHEME= $perlasm_scheme/;
+ s/^PROCESSOR=.*/PROCESSOR= $processor/;
+@@ -1796,6 +1808,7 @@ print "RMD160_OBJ_ASM=$rmd160_obj\n";
+ print "CMLL_ENC =$cmll_obj\n";
+ print "MODES_OBJ =$modes_obj\n";
+ print "ENGINES_OBJ =$engines_obj\n";
++print "CHAPOLY_ENC =$chapoly_obj\n";
+ print "PROCESSOR =$processor\n";
+ print "RANLIB =$ranlib\n";
+ print "ARFLAGS =$arflags\n";
+@@ -2194,7 +2207,7 @@ sub print_table_entry
+ my ($cc, $cflags, $unistd, $thread_cflag, $sys_id, $lflags,
+ $bn_ops, $cpuid_obj, $bn_obj, $ec_obj, $des_obj, $aes_obj, $bf_obj,
+ $md5_obj, $sha1_obj, $cast_obj, $rc4_obj, $rmd160_obj,
+- $rc5_obj, $wp_obj, $cmll_obj, $modes_obj, $engines_obj,
++ $rc5_obj, $wp_obj, $cmll_obj, $modes_obj, $engines_obj, $chapoly_obj,
+ $perlasm_scheme, $dso_scheme, $shared_target, $shared_cflag,
+ $shared_ldflag, $shared_extension, $ranlib, $arflags, $multilib)=
+ split(/\s*:\s*/,$table{$target} . ":" x 30 , -1);
+@@ -2225,6 +2238,7 @@ sub print_table_entry
+ \$cmll_obj = $cmll_obj
+ \$modes_obj = $modes_obj
+ \$engines_obj = $engines_obj
++\$chapoly_obj = $chapoly_obj
+ \$perlasm_scheme = $perlasm_scheme
+ \$dso_scheme = $dso_scheme
+ \$shared_target= $shared_target
+diff --git a/Makefile.org b/Makefile.org
+index 48469c5..c2c5107 100644
+--- a/Makefile.org
++++ b/Makefile.org
+@@ -91,6 +91,7 @@ BN_ASM= bn_asm.o
+ EC_ASM=
+ DES_ENC= des_enc.o fcrypt_b.o
+ AES_ENC= aes_core.o aes_cbc.o
++CHAPOLY_ENC=
+ BF_ENC= bf_enc.o
+ CAST_ENC= c_enc.o
+ RC4_ENC= rc4_enc.o
+@@ -148,7 +149,7 @@ SDIRS= \
+ bn ec rsa dsa ecdsa dh ecdh dso engine \
+ buffer bio stack lhash rand err \
+ evp asn1 pem x509 x509v3 conf txt_db pkcs7 pkcs12 comp ocsp ui krb5 \
+- cms pqueue ts jpake srp store cmac
++ cms pqueue ts jpake srp store cmac chacha20poly1305
+ # keep in mind that the above list is adjusted by ./Configure
+ # according to no-xxx arguments...
+
+@@ -233,6 +234,7 @@ BUILDENV= PLATFORM='$(PLATFORM)' PROCESSOR='$(PROCESSOR)' \
+ WP_ASM_OBJ='$(WP_ASM_OBJ)' \
+ MODES_ASM_OBJ='$(MODES_ASM_OBJ)' \
+ ENGINES_ASM_OBJ='$(ENGINES_ASM_OBJ)' \
++ CHAPOLY_ENC='$(CHAPOLY_ENC)' \
+ PERLASM_SCHEME='$(PERLASM_SCHEME)' \
+ FIPSLIBDIR='${FIPSLIBDIR}' \
+ FIPSDIR='${FIPSDIR}' \
+diff --git a/apps/speed.c b/apps/speed.c
+index 3697b71..ecf7817 100644
+--- a/apps/speed.c
++++ b/apps/speed.c
+@@ -226,7 +226,7 @@
+ # endif
+
+ # undef BUFSIZE
+-# define BUFSIZE ((long)1024*8+1)
++# define BUFSIZE ((long)1024*8+16)
+ static volatile int run = 0;
+
+ static int mr = 0;
+@@ -241,7 +241,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 30
++# define ALGOR_NUM 31
+ # define SIZE_NUM 5
+ # define RSA_NUM 4
+ # define DSA_NUM 3
+@@ -256,7 +256,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", "ghash"
++ "aes-128 ige", "aes-192 ige", "aes-256 ige", "ghash", "chacha20-poly1305"
+ };
+
+ static double results[ALGOR_NUM][SIZE_NUM];
+@@ -516,6 +516,7 @@ int MAIN(int argc, char **argv)
+ # define D_IGE_192_AES 27
+ # define D_IGE_256_AES 28
+ # define D_GHASH 29
++# define D_CHAPOLY 30
+ double d = 0.0;
+ long c[ALGOR_NUM][SIZE_NUM];
+ # define R_DSA_512 0
+@@ -972,6 +973,11 @@ int MAIN(int argc, char **argv)
+ doit[D_CBC_256_CML] = 1;
+ } else
+ # endif
++# ifndef OPENSSL_NO_CHACHA_POLY
++ if (strcmp(*argv,"chacha20-poly1305") == 0) {
++ doit[D_CHAPOLY] = 1;
++ } else
++# endif
+ # ifndef OPENSSL_NO_RSA
+ if (strcmp(*argv, "rsa") == 0) {
+ rsa_doit[R_RSA_512] = 1;
+@@ -1139,7 +1145,9 @@ int MAIN(int argc, char **argv)
+ BIO_printf(bio_err, "rc4");
+ # endif
+ BIO_printf(bio_err, "\n");
+-
++# ifndef OPENSSL_NO_CHACHA_POLY
++ BIO_printf(bio_err,"chacha20-poly1305\n");
++# endif
+ # ifndef OPENSSL_NO_RSA
+ BIO_printf(bio_err, "rsa512 rsa1024 rsa2048 rsa4096\n");
+ # endif
+@@ -1370,6 +1378,7 @@ int MAIN(int argc, char **argv)
+ c[D_IGE_192_AES][0] = count;
+ c[D_IGE_256_AES][0] = count;
+ c[D_GHASH][0] = count;
++ c[D_CHAPOLY][0] = count;
+
+ for (i = 1; i < SIZE_NUM; i++) {
+ c[D_MD2][i] = c[D_MD2][0] * 4 * lengths[0] / lengths[i];
+@@ -1862,6 +1871,23 @@ int MAIN(int argc, char **argv)
+ }
+ }
+ # endif
++# ifndef OPENSSL_NO_CHACHA_POLY
++ if (doit[D_CHAPOLY]) {
++ EVP_CIPHER_CTX ctx;
++ EVP_CIPHER_CTX_init(&ctx);
++ EVP_CipherInit_ex(&ctx,EVP_chacha20_poly1305(),NULL,key32,NULL,1);
++ for (j=0; j<SIZE_NUM; j++) {
++ print_message(names[D_CHAPOLY],c[D_CHAPOLY][j],lengths[j]);
++ Time_F(START);
++ for (count=0,run=1; COND(c[D_CHAPOLY][j]); count++) {
++ EVP_CIPHER_CTX_ctrl(&ctx,EVP_CTRL_AEAD_TLS1_AAD,13,buf);
++ EVP_Cipher(&ctx,buf,buf,(unsigned long)lengths[j]+16);
++ }
++ d=Time_F(STOP);
++ print_result(D_CHAPOLY,j,count,d);
++ }
++ }
++# endif
+ # ifndef OPENSSL_NO_IDEA
+ if (doit[D_CBC_IDEA]) {
+ for (j = 0; j < SIZE_NUM; j++) {
+diff --git a/crypto/chacha20poly1305/Makefile b/crypto/chacha20poly1305/Makefile
+new file mode 100644
+index 0000000..f21dd2e
+--- /dev/null
++++ b/crypto/chacha20poly1305/Makefile
+@@ -0,0 +1,92 @@
++#
++# crypto/chacha20poly1305/Makefile
++#
++DIR= chacha20poly1305
++TOP= ../..
++CC= cc
++CPP= $(CC) -E
++INCLUDES=
++CFLAG=-g
++MAKEFILE= Makefile
++AR= ar r
++
++
++CHAPOLY_ENC=
++
++CFLAGS= $(INCLUDES) $(CFLAG)
++ASFLAGS= $(INCLUDES) $(ASFLAG)
++AFLAGS= $(ASFLAGS)
++
++GENERAL=Makefile
++TEST=chapolytest.c
++APPS=
++
++LIB=$(TOP)/libcrypto.a
++LIBSRC=chacha20.c poly1305.c
++LIBOBJ=chacha20.o poly1305.o $(CHAPOLY_ENC)
++
++SRC= $(LIBSRC)
++
++EXHEADER=chacha20poly1305.h
++HEADER= $(EXHEADER)
++
++ALL= $(GENERAL) $(SRC) $(HEADER)
++
++top:
++ (cd ../..; $(MAKE) DIRS=crypto SDIRS=$(DIR) sub_all)
++
++all: lib
++
++lib: $(LIBOBJ)
++ $(AR) $(LIB) $(LIBOBJ)
++ $(RANLIB) $(LIB) || echo Never mind.
++ @touch lib
++
++chacha20_avx.s:asm/chacha20_avx.pl
++ $(PERL) asm/chacha20_avx.pl $(PERLASM_SCHEME) > $@
++poly1305_avx.s:asm/poly1305_avx.pl
++ $(PERL) asm/poly1305_avx.pl $(PERLASM_SCHEME) > $@
++chacha20_avx2.s:asm/chacha20_avx2.pl
++ $(PERL) asm/chacha20_avx2.pl $(PERLASM_SCHEME) > $@
++poly1305_avx2.s:asm/poly1305_avx2.pl
++ $(PERL) asm/poly1305_avx2.pl $(PERLASM_SCHEME) > $@
++
++files:
++ $(PERL) $(TOP)/util/files.pl Makefile >> $(TOP)/MINFO
++
++links:
++ @$(PERL) $(TOP)/util/mklink.pl ../../include/openssl $(EXHEADER)
++ @$(PERL) $(TOP)/util/mklink.pl ../../test $(TEST)
++ @$(PERL) $(TOP)/util/mklink.pl ../../apps $(APPS)
++
++install:
++ @[ -n "$(INSTALLTOP)" ] # should be set by top Makefile...
++ @headerlist="$(EXHEADER)"; for i in $$headerlist ; \
++ do \
++ (cp $$i $(INSTALL_PREFIX)$(INSTALLTOP)/include/openssl/$$i; \
++ chmod 644 $(INSTALL_PREFIX)$(INSTALLTOP)/include/openssl/$$i ); \
++ done;
++
++tags:
++ ctags $(SRC)
++
++tests:
++
++lint:
++ lint -DLINT $(INCLUDES) $(SRC)>fluff
++
++depend:
++ @[ -n "$(MAKEDEPEND)" ] # should be set by upper Makefile...
++ $(MAKEDEPEND) -- $(CFLAG) $(INCLUDES) $(DEPFLAG) -- $(PROGS) $(LIBSRC)
++
++dclean:
++ $(PERL) -pe 'if (/^# DO NOT DELETE THIS LINE/) {print; exit(0);}' $(MAKEFILE) >Makefile.new
++ mv -f Makefile.new $(MAKEFILE)
++
++clean:
++ rm -f *.s *.o *.obj lib tags core .pure .nfs* *.old *.bak fluff
++
++# DO NOT DELETE THIS LINE -- make depend depends on it.
++
++chacha20.o: ../../include/openssl/chacha20poly1305.h chacha20.c
++poly1305.o: ../../include/openssl/chacha20poly1305.h poly1305.c
+diff --git a/crypto/chacha20poly1305/asm/chacha20_avx.pl b/crypto/chacha20poly1305/asm/chacha20_avx.pl
+new file mode 100644
+index 0000000..7b5b763
+--- /dev/null
++++ b/crypto/chacha20poly1305/asm/chacha20_avx.pl
+@@ -0,0 +1,388 @@
++#!/usr/bin/env perl
++
++##############################################################################
++# #
++# Copyright 2014 Intel Corporation #
++# #
++# Licensed under the Apache License, Version 2.0 (the "License"); #
++# you may not use this file except in compliance with the License. #
++# You may obtain a copy of the License at #
++# #
++# http://www.apache.org/licenses/LICENSE-2.0 #
++# #
++# Unless required by applicable law or agreed to in writing, software #
++# distributed under the License is distributed on an "AS IS" BASIS, #
++# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
++# See the License for the specific language governing permissions and #
++# limitations under the License. #
++# #
++##############################################################################
++# #
++# Developers and authors: #
++# Shay Gueron (1, 2), and Vlad Krasnov (1) #
++# (1) Intel Corporation, Israel Development Center #
++# (2) University of Haifa #
++# #
++# Related work: #
++# M. Goll, S. Gueron, "Vectorization on ChaCha Stream Cipher", IEEE #
++# Proceedings of 11th International Conference on Information #
++# Technology: New Generations (ITNG 2014), 612-615 (2014). #
++# M. Goll, S. Gueron, "Vectorization on Poly1305 Message Authentication Code"#
++# to be published. #
++# A. Langley, chacha20poly1305 for the AEAD head #
++# https://git.openssl.org/gitweb/?p=openssl.git;a=commit;h=9a8646510b3d0a48e950748f7a2aaa12ed40d5e0 #
++##############################################################################
++
++
++
++$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";
++
++open OUT,"| \"$^X\" $xlate $flavour $output";
++*STDOUT=*OUT;
++
++if (`$ENV{CC} -Wa,-v -c -o /dev/null -x assembler /dev/null 2>&1`
++ =~ /GNU assembler version ([2-9]\.[0-9]+)/) {
++ $avx = ($1>=2.19) + ($1>=2.22);
++}
++
++if ($win64 && ($flavour =~ /nasm/ || $ENV{ASM} =~ /nasm/) &&
++ `nasm -v 2>&1` =~ /NASM version ([2-9]\.[0-9]+)/) {
++ $avx = ($1>=2.09) + ($1>=2.10);
++}
++
++if ($win64 && ($flavour =~ /masm/ || $ENV{ASM} =~ /ml64/) &&
++ `ml64 2>&1` =~ /Version ([0-9]+)\./) {
++ $avx = ($1>=10) + ($1>=11);
++}
++
++if (`$ENV{CC} -v 2>&1` =~ /(^clang version|based on LLVM) ([3-9])\.([0-9]+)/) {
++ my $ver = $2 + $3/100.0; # 3.1->3.01, 3.10->3.10
++ $avx = ($ver>=3.0) + ($ver>=3.01);
++}
++
++if ($avx>=1) {{
++
++sub chacha_qr {
++my ($a,$b,$c,$d,$tmp)=@_;
++$code.=<<___;
++
++ vpaddd $b, $a, $a # a += b
++ vpxor $a, $d, $d # d ^= a
++ vpshufb .rol16(%rip), $d, $d # d <<<= 16
++
++ vpaddd $d, $c, $c # c += d
++ vpxor $c, $b, $b # b ^= c
++ vpslld \$12, $b, $tmp
++ vpsrld \$20, $b, $b
++ vpxor $tmp, $b, $b # b <<<= 12
++
++ vpaddd $b, $a, $a # a += b
++ vpxor $a, $d, $d # d ^= a
++ vpshufb .rol8(%rip), $d, $d # d <<<= 8
++
++ vpaddd $d, $c, $c # c += d
++ vpxor $c, $b, $b # b ^= c
++
++ vpslld \$7, $b, $tmp
++ vpsrld \$25, $b, $b
++ vpxor $tmp, $b, $b # b <<<= 7
++___
++}
++
++
++$code.=<<___;
++.text
++.align 16
++chacha20_consts:
++.byte 'e','x','p','a','n','d',' ','3','2','-','b','y','t','e',' ','k'
++.rol8:
++.byte 3,0,1,2, 7,4,5,6, 11,8,9,10, 15,12,13,14
++.rol16:
++.byte 2,3,0,1, 6,7,4,5, 10,11,8,9, 14,15,12,13
++.avxInc:
++.quad 1,0
++___
++
++{
++my ($state_4567, $state_89ab, $state_cdef, $tmp,
++ $v0, $v1, $v2, $v3, $v4, $v5, $v6, $v7,
++ $v8, $v9, $v10, $v11)=map("%xmm$_",(0..15));
++
++my ($out, $in, $in_len, $key_ptr, $nonce_ptr, $counter, $nr)
++ =("%rdi", "%rsi", "%rdx", "%rcx", "%r8", "%r9", "%rax");
++
++$code.=<<___;
++.globl chacha_20_core_avx
++.type chacha_20_core_avx ,\@function,2
++.align 64
++chacha_20_core_avx:
++ vzeroupper
++
++ # Init state
++ vmovdqu 16*0($key_ptr), $state_4567
++ vmovdqu 16*1($key_ptr), $state_89ab
++ vmovq $counter, $state_cdef
++ vpinsrq \$1, ($nonce_ptr), $state_cdef, $state_cdef
++2:
++ cmp \$3*64, $in_len
++ jb 2f
++
++ vmovdqa chacha20_consts(%rip), $v0
++ vmovdqa chacha20_consts(%rip), $v4
++ vmovdqa chacha20_consts(%rip), $v8
++
++ vmovdqa $state_4567, $v1
++ vmovdqa $state_4567, $v5
++ vmovdqa $state_4567, $v9
++
++ vmovdqa $state_89ab, $v2
++ vmovdqa $state_89ab, $v6
++ vmovdqa $state_89ab, $v10
++
++ vmovdqa $state_cdef, $v3
++ vpaddq .avxInc(%rip), $v3, $v7
++ vpaddq .avxInc(%rip), $v7, $v11
++
++ mov \$10, $nr
++
++ 1:
++___
++ &chacha_qr($v0,$v1,$v2,$v3,$tmp);
++ &chacha_qr($v4,$v5,$v6,$v7,$tmp);
++ &chacha_qr($v8,$v9,$v10,$v11,$tmp);
++$code.=<<___;
++ vpalignr \$4, $v1, $v1, $v1
++ vpalignr \$8, $v2, $v2, $v2
++ vpalignr \$12, $v3, $v3, $v3
++ vpalignr \$4, $v5, $v5, $v5
++ vpalignr \$8, $v6, $v6, $v6
++ vpalignr \$12, $v7, $v7, $v7
++ vpalignr \$4, $v9, $v9, $v9
++ vpalignr \$8, $v10, $v10, $v10
++ vpalignr \$12, $v11, $v11, $v11
++___
++ &chacha_qr($v0,$v1,$v2,$v3,$tmp);
++ &chacha_qr($v4,$v5,$v6,$v7,$tmp);
++ &chacha_qr($v8,$v9,$v10,$v11,$tmp);
++$code.=<<___;
++ vpalignr \$12, $v1, $v1, $v1
++ vpalignr \$8, $v2, $v2, $v2
++ vpalignr \$4, $v3, $v3, $v3
++ vpalignr \$12, $v5, $v5, $v5
++ vpalignr \$8, $v6, $v6, $v6
++ vpalignr \$4, $v7, $v7, $v7
++ vpalignr \$12, $v9, $v9, $v9
++ vpalignr \$8, $v10, $v10, $v10
++ vpalignr \$4, $v11, $v11, $v11
++
++ dec $nr
++
++ jnz 1b
++
++ vpaddd chacha20_consts(%rip), $v0, $v0
++ vpaddd chacha20_consts(%rip), $v4, $v4
++ vpaddd chacha20_consts(%rip), $v8, $v8
++
++ vpaddd $state_4567, $v1, $v1
++ vpaddd $state_4567, $v5, $v5
++ vpaddd $state_4567, $v9, $v9
++
++ vpaddd $state_89ab, $v2, $v2
++ vpaddd $state_89ab, $v6, $v6
++ vpaddd $state_89ab, $v10, $v10
++
++ vpaddd $state_cdef, $v3, $v3
++ vpaddq .avxInc(%rip), $state_cdef, $state_cdef
++ vpaddd $state_cdef, $v7, $v7
++ vpaddq .avxInc(%rip), $state_cdef, $state_cdef
++ vpaddd $state_cdef, $v11, $v11
++ vpaddq .avxInc(%rip), $state_cdef, $state_cdef
++
++ vpxor 16*0($in), $v0, $v0
++ vpxor 16*1($in), $v1, $v1
++ vpxor 16*2($in), $v2, $v2
++ vpxor 16*3($in), $v3, $v3
++
++ vmovdqu $v0, 16*0($out)
++ vmovdqu $v1, 16*1($out)
++ vmovdqu $v2, 16*2($out)
++ vmovdqu $v3, 16*3($out)
++
++ vpxor 16*4($in), $v4, $v4
++ vpxor 16*5($in), $v5, $v5
++ vpxor 16*6($in), $v6, $v6
++ vpxor 16*7($in), $v7, $v7
++
++ vmovdqu $v4, 16*4($out)
++ vmovdqu $v5, 16*5($out)
++ vmovdqu $v6, 16*6($out)
++ vmovdqu $v7, 16*7($out)
++
++ vpxor 16*8($in), $v8, $v8
++ vpxor 16*9($in), $v9, $v9
++ vpxor 16*10($in), $v10, $v10
++ vpxor 16*11($in), $v11, $v11
++
++ vmovdqu $v8, 16*8($out)
++ vmovdqu $v9, 16*9($out)
++ vmovdqu $v10, 16*10($out)
++ vmovdqu $v11, 16*11($out)
++
++ lea 16*12($in), $in
++ lea 16*12($out), $out
++ sub \$16*12, $in_len
++
++ jmp 2b
++
++2:
++ cmp \$2*64, $in_len
++ jb 2f
++
++ vmovdqa chacha20_consts(%rip), $v0
++ vmovdqa chacha20_consts(%rip), $v4
++ vmovdqa $state_4567, $v1
++ vmovdqa $state_4567, $v5
++ vmovdqa $state_89ab, $v2
++ vmovdqa $state_89ab, $v6
++ vmovdqa $state_89ab, $v10
++ vmovdqa $state_cdef, $v3
++ vpaddq .avxInc(%rip), $v3, $v7
++
++ mov \$10, $nr
++
++ 1:
++___
++ &chacha_qr($v0,$v1,$v2,$v3,$tmp);
++ &chacha_qr($v4,$v5,$v6,$v7,$tmp);
++$code.=<<___;
++ vpalignr \$4, $v1, $v1, $v1
++ vpalignr \$8, $v2, $v2, $v2
++ vpalignr \$12, $v3, $v3, $v3
++ vpalignr \$4, $v5, $v5, $v5
++ vpalignr \$8, $v6, $v6, $v6
++ vpalignr \$12, $v7, $v7, $v7
++___
++ &chacha_qr($v0,$v1,$v2,$v3,$tmp);
++ &chacha_qr($v4,$v5,$v6,$v7,$tmp);
++$code.=<<___;
++ vpalignr \$12, $v1, $v1, $v1
++ vpalignr \$8, $v2, $v2, $v2
++ vpalignr \$4, $v3, $v3, $v3
++ vpalignr \$12, $v5, $v5, $v5
++ vpalignr \$8, $v6, $v6, $v6
++ vpalignr \$4, $v7, $v7, $v7
++
++ dec $nr
++
++ jnz 1b
++
++ vpaddd chacha20_consts(%rip), $v0, $v0
++ vpaddd chacha20_consts(%rip), $v4, $v4
++
++ vpaddd $state_4567, $v1, $v1
++ vpaddd $state_4567, $v5, $v5
++
++ vpaddd $state_89ab, $v2, $v2
++ vpaddd $state_89ab, $v6, $v6
++
++ vpaddd $state_cdef, $v3, $v3
++ vpaddq .avxInc(%rip), $state_cdef, $state_cdef
++ vpaddd $state_cdef, $v7, $v7
++ vpaddq .avxInc(%rip), $state_cdef, $state_cdef
++
++ vpxor 16*0($in), $v0, $v0
++ vpxor 16*1($in), $v1, $v1
++ vpxor 16*2($in), $v2, $v2
++ vpxor 16*3($in), $v3, $v3
++
++ vmovdqu $v0, 16*0($out)
++ vmovdqu $v1, 16*1($out)
++ vmovdqu $v2, 16*2($out)
++ vmovdqu $v3, 16*3($out)
++
++ vpxor 16*4($in), $v4, $v4
++ vpxor 16*5($in), $v5, $v5
++ vpxor 16*6($in), $v6, $v6
++ vpxor 16*7($in), $v7, $v7
++
++ vmovdqu $v4, 16*4($out)
++ vmovdqu $v5, 16*5($out)
++ vmovdqu $v6, 16*6($out)
++ vmovdqu $v7, 16*7($out)
++
++ lea 16*8($in), $in
++ lea 16*8($out), $out
++ sub \$16*8, $in_len
++
++ jmp 2b
++2:
++ cmp \$64, $in_len
++ jb 2f
++
++ vmovdqa chacha20_consts(%rip), $v0
++ vmovdqa $state_4567, $v1
++ vmovdqa $state_89ab, $v2
++ vmovdqa $state_cdef, $v3
++
++ mov \$10, $nr
++
++ 1:
++___
++ &chacha_qr($v0,$v1,$v2,$v3,$tmp);
++$code.=<<___;
++ vpalignr \$4, $v1, $v1, $v1
++ vpalignr \$8, $v2, $v2, $v2
++ vpalignr \$12, $v3, $v3, $v3
++___
++ &chacha_qr($v0,$v1,$v2,$v3,$tmp);
++$code.=<<___;
++ vpalignr \$12, $v1, $v1, $v1
++ vpalignr \$8, $v2, $v2, $v2
++ vpalignr \$4, $v3, $v3, $v3
++
++ dec $nr
++ jnz 1b
++
++ vpaddd chacha20_consts(%rip), $v0, $v0
++ vpaddd $state_4567, $v1, $v1
++ vpaddd $state_89ab, $v2, $v2
++ vpaddd $state_cdef, $v3, $v3
++ vpaddq .avxInc(%rip), $state_cdef, $state_cdef
++
++ vpxor 16*0($in), $v0, $v0
++ vpxor 16*1($in), $v1, $v1
++ vpxor 16*2($in), $v2, $v2
++ vpxor 16*3($in), $v3, $v3
++
++ vmovdqu $v0, 16*0($out)
++ vmovdqu $v1, 16*1($out)
++ vmovdqu $v2, 16*2($out)
++ vmovdqu $v3, 16*3($out)
++
++ lea 16*4($in), $in
++ lea 16*4($out), $out
++ sub \$16*4, $in_len
++ jmp 2b
++2:
++ vzeroupper
++ ret
++.size chacha_20_core_avx,.-chacha_20_core_avx
++___
++}
++}}
++
++
++$code =~ s/\`([^\`]*)\`/eval($1)/gem;
++
++print $code;
++
++close STDOUT;
+diff --git a/crypto/chacha20poly1305/asm/chacha20_avx2.pl b/crypto/chacha20poly1305/asm/chacha20_avx2.pl
+new file mode 100644
+index 0000000..31ae721
+--- /dev/null
++++ b/crypto/chacha20poly1305/asm/chacha20_avx2.pl
+@@ -0,0 +1,424 @@
++#!/usr/bin/env perl
++
++##############################################################################
++# #
++# Copyright 2014 Intel Corporation #
++# #
++# Licensed under the Apache License, Version 2.0 (the "License"); #
++# you may not use this file except in compliance with the License. #
++# You may obtain a copy of the License at #
++# #
++# http://www.apache.org/licenses/LICENSE-2.0 #
++# #
++# Unless required by applicable law or agreed to in writing, software #
++# distributed under the License is distributed on an "AS IS" BASIS, #
++# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
++# See the License for the specific language governing permissions and #
++# limitations under the License. #
++# #
++##############################################################################
++# #
++# Developers and authors: #
++# Shay Gueron (1, 2), and Vlad Krasnov (1) #
++# (1) Intel Corporation, Israel Development Center #
++# (2) University of Haifa #
++# #
++# Related work: #
++# M. Goll, S. Gueron, "Vectorization on ChaCha Stream Cipher", IEEE #
++# Proceedings of 11th International Conference on Information #
++# Technology: New Generations (ITNG 2014), 612-615 (2014). #
++# M. Goll, S. Gueron, "Vectorization on Poly1305 Message Authentication Code"#
++# to be published. #
++# A. Langley, chacha20poly1305 for the AEAD head #
++# https://git.openssl.org/gitweb/?p=openssl.git;a=commit;h=9a8646510b3d0a48e950748f7a2aaa12ed40d5e0 #
++##############################################################################
++
++$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";
++
++open OUT,"| \"$^X\" $xlate $flavour $output";
++*STDOUT=*OUT;
++
++if (`$ENV{CC} -Wa,-v -c -o /dev/null -x assembler /dev/null 2>&1`
++ =~ /GNU assembler version ([2-9]\.[0-9]+)/) {
++ $avx = ($1>=2.19) + ($1>=2.22);
++}
++
++if ($win64 && ($flavour =~ /nasm/ || $ENV{ASM} =~ /nasm/) &&
++ `nasm -v 2>&1` =~ /NASM version ([2-9]\.[0-9]+)/) {
++ $avx = ($1>=2.09) + ($1>=2.10);
++}
++
++if ($win64 && ($flavour =~ /masm/ || $ENV{ASM} =~ /ml64/) &&
++ `ml64 2>&1` =~ /Version ([0-9]+)\./) {
++ $avx = ($1>=10) + ($1>=11);
++}
++
++if (`$ENV{CC} -v 2>&1` =~ /(^clang version|based on LLVM) ([3-9])\.([0-9]+)/) {
++ my $ver = $2 + $3/100.0; # 3.1->3.01, 3.10->3.10
++ $avx = ($ver>=3.0) + ($ver>=3.01);
++}
++
++if ($avx>=2) {{
++
++sub chacha_qr {
++my ($a,$b,$c,$d,$tmp)=@_;
++$code.=<<___;
++
++ vpaddd $b, $a, $a # a += b
++ vpxor $a, $d, $d # d ^= a
++ vpshufb .rol16(%rip), $d, $d # d <<<= 16
++
++ vpaddd $d, $c, $c # c += d
++ vpxor $c, $b, $b # b ^= c
++ vpslld \$12, $b, $tmp
++ vpsrld \$20, $b, $b
++ vpxor $tmp, $b, $b # b <<<= 12
++
++ vpaddd $b, $a, $a # a += b
++ vpxor $a, $d, $d # d ^= a
++ vpshufb .rol8(%rip), $d, $d # d <<<= 8
++
++ vpaddd $d, $c, $c # c += d
++ vpxor $c, $b, $b # b ^= c
++
++ vpslld \$7, $b, $tmp
++ vpsrld \$25, $b, $b
++ vpxor $tmp, $b, $b # b <<<= 7
++___
++}
++
++
++$code.=<<___;
++.text
++.align 32
++chacha20_consts:
++.byte 'e','x','p','a','n','d',' ','3','2','-','b','y','t','e',' ','k'
++.byte 'e','x','p','a','n','d',' ','3','2','-','b','y','t','e',' ','k'
++.rol8:
++.byte 3,0,1,2, 7,4,5,6, 11,8,9,10, 15,12,13,14
++.byte 3,0,1,2, 7,4,5,6, 11,8,9,10, 15,12,13,14
++.rol16:
++.byte 2,3,0,1, 6,7,4,5, 10,11,8,9, 14,15,12,13
++.byte 2,3,0,1, 6,7,4,5, 10,11,8,9, 14,15,12,13
++.avx2Init:
++.quad 0,0,1,0
++.avx2Inc:
++.quad 2,0,2,0
++___
++
++{
++my ($state_4567, $state_89ab, $state_cdef, $tmp,
++ $v0, $v1, $v2, $v3, $v4, $v5, $v6, $v7,
++ $v8, $v9, $v10, $v11)=map("%ymm$_",(0..15));
++
++my $state_cdef_xmm="%xmm2";
++
++my ($out, $in, $in_len, $key_ptr, $nonce_ptr, $counter, $nr)
++ =("%rdi", "%rsi", "%rdx", "%rcx", "%r8", "%r9", "%rax");
++
++$code.=<<___;
++.globl chacha_20_core_avx2
++.type chacha_20_core_avx2 ,\@function,2
++.align 64
++chacha_20_core_avx2:
++ vzeroupper
++
++ # Init state
++ vbroadcasti128 16*0($key_ptr), $state_4567
++ vbroadcasti128 16*1($key_ptr), $state_89ab
++ vmovq $counter, $state_cdef_xmm
++ vpinsrq \$1, ($nonce_ptr), $state_cdef_xmm, $state_cdef_xmm
++ vperm2i128 \$0x00, $state_cdef, $state_cdef, $state_cdef
++ vpaddq .avx2Init(%rip), $state_cdef, $state_cdef
++
++2:
++ cmp \$6*64, $in_len
++ jb 2f
++
++ vmovdqa chacha20_consts(%rip), $v0
++ vmovdqa chacha20_consts(%rip), $v4
++ vmovdqa chacha20_consts(%rip), $v8
++
++ vmovdqa $state_4567, $v1
++ vmovdqa $state_4567, $v5
++ vmovdqa $state_4567, $v9
++
++ vmovdqa $state_89ab, $v2
++ vmovdqa $state_89ab, $v6
++ vmovdqa $state_89ab, $v10
++
++ vmovdqa $state_cdef, $v3
++ vpaddq .avx2Inc(%rip), $v3, $v7
++ vpaddq .avx2Inc(%rip), $v7, $v11
++
++ mov \$10, $nr
++
++ 1:
++___
++ &chacha_qr($v0,$v1,$v2,$v3,$tmp);
++ &chacha_qr($v4,$v5,$v6,$v7,$tmp);
++ &chacha_qr($v8,$v9,$v10,$v11,$tmp);
++$code.=<<___;
++ vpalignr \$4, $v1, $v1, $v1
++ vpalignr \$8, $v2, $v2, $v2
++ vpalignr \$12, $v3, $v3, $v3
++ vpalignr \$4, $v5, $v5, $v5
++ vpalignr \$8, $v6, $v6, $v6
++ vpalignr \$12, $v7, $v7, $v7
++ vpalignr \$4, $v9, $v9, $v9
++ vpalignr \$8, $v10, $v10, $v10
++ vpalignr \$12, $v11, $v11, $v11
++___
++ &chacha_qr($v0,$v1,$v2,$v3,$tmp);
++ &chacha_qr($v4,$v5,$v6,$v7,$tmp);
++ &chacha_qr($v8,$v9,$v10,$v11,$tmp);
++$code.=<<___;
++ vpalignr \$12, $v1, $v1, $v1
++ vpalignr \$8, $v2, $v2, $v2
++ vpalignr \$4, $v3, $v3, $v3
++ vpalignr \$12, $v5, $v5, $v5
++ vpalignr \$8, $v6, $v6, $v6
++ vpalignr \$4, $v7, $v7, $v7
++ vpalignr \$12, $v9, $v9, $v9
++ vpalignr \$8, $v10, $v10, $v10
++ vpalignr \$4, $v11, $v11, $v11
++
++ dec $nr
++
++ jnz 1b
++
++ vpaddd chacha20_consts(%rip), $v0, $v0
++ vpaddd chacha20_consts(%rip), $v4, $v4
++ vpaddd chacha20_consts(%rip), $v8, $v8
++
++ vpaddd $state_4567, $v1, $v1
++ vpaddd $state_4567, $v5, $v5
++ vpaddd $state_4567, $v9, $v9
++
++ vpaddd $state_89ab, $v2, $v2
++ vpaddd $state_89ab, $v6, $v6
++ vpaddd $state_89ab, $v10, $v10
++
++ vpaddd $state_cdef, $v3, $v3
++ vpaddq .avx2Inc(%rip), $state_cdef, $state_cdef
++ vpaddd $state_cdef, $v7, $v7
++ vpaddq .avx2Inc(%rip), $state_cdef, $state_cdef
++ vpaddd $state_cdef, $v11, $v11
++ vpaddq .avx2Inc(%rip), $state_cdef, $state_cdef
++
++ vperm2i128 \$0x02, $v0, $v1, $tmp
++ vpxor 32*0($in), $tmp, $tmp
++ vmovdqu $tmp, 32*0($out)
++ vperm2i128 \$0x02, $v2, $v3, $tmp
++ vpxor 32*1($in), $tmp, $tmp
++ vmovdqu $tmp, 32*1($out)
++ vperm2i128 \$0x13, $v0, $v1, $tmp
++ vpxor 32*2($in), $tmp, $tmp
++ vmovdqu $tmp, 32*2($out)
++ vperm2i128 \$0x13, $v2, $v3, $tmp
++ vpxor 32*3($in), $tmp, $tmp
++ vmovdqu $tmp, 32*3($out)
++
++ vperm2i128 \$0x02, $v4, $v5, $v0
++ vperm2i128 \$0x02, $v6, $v7, $v1
++ vperm2i128 \$0x13, $v4, $v5, $v2
++ vperm2i128 \$0x13, $v6, $v7, $v3
++
++ vpxor 32*4($in), $v0, $v0
++ vpxor 32*5($in), $v1, $v1
++ vpxor 32*6($in), $v2, $v2
++ vpxor 32*7($in), $v3, $v3
++
++ vmovdqu $v0, 32*4($out)
++ vmovdqu $v1, 32*5($out)
++ vmovdqu $v2, 32*6($out)
++ vmovdqu $v3, 32*7($out)
++
++ vperm2i128 \$0x02, $v8, $v9, $v0
++ vperm2i128 \$0x02, $v10, $v11, $v1
++ vperm2i128 \$0x13, $v8, $v9, $v2
++ vperm2i128 \$0x13, $v10, $v11, $v3
++
++ vpxor 32*8($in), $v0, $v0
++ vpxor 32*9($in), $v1, $v1
++ vpxor 32*10($in), $v2, $v2
++ vpxor 32*11($in), $v3, $v3
++
++ vmovdqu $v0, 32*8($out)
++ vmovdqu $v1, 32*9($out)
++ vmovdqu $v2, 32*10($out)
++ vmovdqu $v3, 32*11($out)
++
++ lea 64*6($in), $in
++ lea 64*6($out), $out
++ sub \$64*6, $in_len
++
++ jmp 2b
++
++2:
++ cmp \$4*64, $in_len
++ jb 2f
++
++ vmovdqa chacha20_consts(%rip), $v0
++ vmovdqa chacha20_consts(%rip), $v4
++ vmovdqa $state_4567, $v1
++ vmovdqa $state_4567, $v5
++ vmovdqa $state_89ab, $v2
++ vmovdqa $state_89ab, $v6
++ vmovdqa $state_89ab, $v10
++ vmovdqa $state_cdef, $v3
++ vpaddq .avx2Inc(%rip), $v3, $v7
++
++ mov \$10, $nr
++
++ 1:
++___
++ &chacha_qr($v0,$v1,$v2,$v3,$tmp);
++ &chacha_qr($v4,$v5,$v6,$v7,$tmp);
++$code.=<<___;
++ vpalignr \$4, $v1, $v1, $v1
++ vpalignr \$8, $v2, $v2, $v2
++ vpalignr \$12, $v3, $v3, $v3
++ vpalignr \$4, $v5, $v5, $v5
++ vpalignr \$8, $v6, $v6, $v6
++ vpalignr \$12, $v7, $v7, $v7
++___
++ &chacha_qr($v0,$v1,$v2,$v3,$tmp);
++ &chacha_qr($v4,$v5,$v6,$v7,$tmp);
++$code.=<<___;
++ vpalignr \$12, $v1, $v1, $v1
++ vpalignr \$8, $v2, $v2, $v2
++ vpalignr \$4, $v3, $v3, $v3
++ vpalignr \$12, $v5, $v5, $v5
++ vpalignr \$8, $v6, $v6, $v6
++ vpalignr \$4, $v7, $v7, $v7
++
++ dec $nr
++
++ jnz 1b
++
++ vpaddd chacha20_consts(%rip), $v0, $v0
++ vpaddd chacha20_consts(%rip), $v4, $v4
++
++ vpaddd $state_4567, $v1, $v1
++ vpaddd $state_4567, $v5, $v5
++
++ vpaddd $state_89ab, $v2, $v2
++ vpaddd $state_89ab, $v6, $v6
++
++ vpaddd $state_cdef, $v3, $v3
++ vpaddq .avx2Inc(%rip), $state_cdef, $state_cdef
++ vpaddd $state_cdef, $v7, $v7
++ vpaddq .avx2Inc(%rip), $state_cdef, $state_cdef
++
++ vperm2i128 \$0x02, $v0, $v1, $v8
++ vperm2i128 \$0x02, $v2, $v3, $v9
++ vperm2i128 \$0x13, $v0, $v1, $v10
++ vperm2i128 \$0x13, $v2, $v3, $v11
++
++ vpxor 32*0($in), $v8, $v8
++ vpxor 32*1($in), $v9, $v9
++ vpxor 32*2($in), $v10, $v10
++ vpxor 32*3($in), $v11, $v11
++
++ vmovdqu $v8, 32*0($out)
++ vmovdqu $v9, 32*1($out)
++ vmovdqu $v10, 32*2($out)
++ vmovdqu $v11, 32*3($out)
++
++ vperm2i128 \$0x02, $v4, $v5, $v0
++ vperm2i128 \$0x02, $v6, $v7, $v1
++ vperm2i128 \$0x13, $v4, $v5, $v2
++ vperm2i128 \$0x13, $v6, $v7, $v3
++
++ vpxor 32*4($in), $v0, $v0
++ vpxor 32*5($in), $v1, $v1
++ vpxor 32*6($in), $v2, $v2
++ vpxor 32*7($in), $v3, $v3
++
++ vmovdqu $v0, 32*4($out)
++ vmovdqu $v1, 32*5($out)
++ vmovdqu $v2, 32*6($out)
++ vmovdqu $v3, 32*7($out)
++
++ lea 64*4($in), $in
++ lea 64*4($out), $out
++ sub \$64*4, $in_len
++
++ jmp 2b
++2:
++ cmp \$128, $in_len
++ jb 2f
++
++ vmovdqa chacha20_consts(%rip), $v0
++ vmovdqa $state_4567, $v1
++ vmovdqa $state_89ab, $v2
++ vmovdqa $state_cdef, $v3
++
++ mov \$10, $nr
++
++ 1:
++___
++ &chacha_qr($v0,$v1,$v2,$v3,$tmp);
++$code.=<<___;
++ vpalignr \$4, $v1, $v1, $v1
++ vpalignr \$8, $v2, $v2, $v2
++ vpalignr \$12, $v3, $v3, $v3
++___
++ &chacha_qr($v0,$v1,$v2,$v3,$tmp);
++$code.=<<___;
++ vpalignr \$12, $v1, $v1, $v1
++ vpalignr \$8, $v2, $v2, $v2
++ vpalignr \$4, $v3, $v3, $v3
++
++ dec $nr
++ jnz 1b
++
++ vpaddd chacha20_consts(%rip), $v0, $v0
++ vpaddd $state_4567, $v1, $v1
++ vpaddd $state_89ab, $v2, $v2
++ vpaddd $state_cdef, $v3, $v3
++ vpaddq .avx2Inc(%rip), $state_cdef, $state_cdef
++
++ vperm2i128 \$0x02, $v0, $v1, $v8
++ vperm2i128 \$0x02, $v2, $v3, $v9
++ vperm2i128 \$0x13, $v0, $v1, $v10
++ vperm2i128 \$0x13, $v2, $v3, $v11
++
++ vpxor 32*0($in), $v8, $v8
++ vpxor 32*1($in), $v9, $v9
++ vpxor 32*2($in), $v10, $v10
++ vpxor 32*3($in), $v11, $v11
++
++ vmovdqu $v8, 32*0($out)
++ vmovdqu $v9, 32*1($out)
++ vmovdqu $v10, 32*2($out)
++ vmovdqu $v11, 32*3($out)
++
++ lea 64*2($in), $in
++ lea 64*2($out), $out
++ sub \$64*2, $in_len
++ jmp 2b
++2:
++ vzeroupper
++ ret
++.size chacha_20_core_avx2,.-chacha_20_core_avx2
++___
++}
++}}
++
++
++$code =~ s/\`([^\`]*)\`/eval($1)/gem;
++
++print $code;
++
++close STDOUT;
+diff --git a/crypto/chacha20poly1305/asm/poly1305_avx.pl b/crypto/chacha20poly1305/asm/poly1305_avx.pl
+new file mode 100644
+index 0000000..2d06e41
+--- /dev/null
++++ b/crypto/chacha20poly1305/asm/poly1305_avx.pl
+@@ -0,0 +1,717 @@
++##############################################################################
++# #
++# Copyright 2014 Intel Corporation #
++# #
++# Licensed under the Apache License, Version 2.0 (the "License"); #
++# you may not use this file except in compliance with the License. #
++# You may obtain a copy of the License at #
++# #
++# http://www.apache.org/licenses/LICENSE-2.0 #
++# #
++# Unless required by applicable law or agreed to in writing, software #
++# distributed under the License is distributed on an "AS IS" BASIS, #
++# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
++# See the License for the specific language governing permissions and #
++# limitations under the License. #
++# #
++##############################################################################
++# #
++# Developers and authors: #
++# Shay Gueron (1, 2), and Vlad Krasnov (1) #
++# (1) Intel Corporation, Israel Development Center #
++# (2) University of Haifa #
++# #
++##############################################################################
++# state:
++# 0: r[0] || r^2[0]
++# 16: r[1] || r^2[1]
++# 32: r[2] || r^2[2]
++# 48: r[3] || r^2[3]
++# 64: r[4] || r^2[4]
++# 80: r[1]*5 || r^2[1]*5
++# 96: r[2]*5 || r^2[2]*5
++#112: r[3]*5 || r^2[3]*5
++#128: r[4]*5 || r^2[4]*5
++#144: k
++#160: A0
++#164: A1
++#168: A2
++#172: A3
++#176: A4
++#180: END
++
++$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";
++
++open OUT,"| \"$^X\" $xlate $flavour $output";
++*STDOUT=*OUT;
++
++if (`$ENV{CC} -Wa,-v -c -o /dev/null -x assembler /dev/null 2>&1`
++ =~ /GNU assembler version ([2-9]\.[0-9]+)/) {
++ $avx = ($1>=2.19) + ($1>=2.22);
++}
++
++if ($win64 && ($flavour =~ /nasm/ || $ENV{ASM} =~ /nasm/) &&
++ `nasm -v 2>&1` =~ /NASM version ([2-9]\.[0-9]+)/) {
++ $avx = ($1>=2.09) + ($1>=2.10);
++}
++
++if ($win64 && ($flavour =~ /masm/ || $ENV{ASM} =~ /ml64/) &&
++ `ml64 2>&1` =~ /Version ([0-9]+)\./) {
++ $avx = ($1>=10) + ($1>=11);
++}
++
++if (`$ENV{CC} -v 2>&1` =~ /(^clang version|based on LLVM) ([3-9])\.([0-9]+)/) {
++ my $ver = $2 + $3/100.0; # 3.1->3.01, 3.10->3.10
++ $avx = ($ver>=3.0) + ($ver>=3.01);
++}
++
++if ($avx>=1) {{
++
++my ($_r0_, $_r1_, $_r2_, $_r3_, $_r4_, $_r1_x5, $_r2_x5, $_r3_x5, $_r4_x5, $_k_, $_A0_, $_A1_, $_A2_, $_A3_, $_A4_)
++= (0,16,32,48,64,80,96,112,128,144,160,164,168,172,176);
++
++$code.=<<___;
++.text
++.align 32
++.LandMask:
++.quad 0x3FFFFFF, 0x3FFFFFF
++.LsetBit:
++.quad 0x1000000, 0x1000000
++.LrSet:
++.quad 0xFFFFFFC0FFFFFFF, 0xFFFFFFC0FFFFFFF
++.quad 0xFFFFFFC0FFFFFFC, 0xFFFFFFC0FFFFFFC
++.Lone:
++.quad 1,0
++___
++
++
++{
++my ($A0, $A1, $A2, $A3, $A4,
++ $r0, $r1, $r2, $r3, $r4,
++ $T0, $T1, $A5, $A6, $A7, $A8)=map("%xmm$_",(0..15));
++my ($state, $key)
++ =("%rdi", "%rsi");
++
++$code.=<<___;
++################################################################################
++# void poly1305_init_avx(void *state, uint8_t key[32])
++
++.globl poly1305_init_avx
++.type poly1305_init_avx, \@function, 2
++.align 64
++poly1305_init_avx:
++ vzeroupper
++ # load and convert r
++ vmovq 8*0($key), $r0
++ vmovq 8*1($key), $T0
++ vpand .LrSet(%rip), $r0, $r0
++ vpand .LrSet+16(%rip), $T0, $T0
++
++ vpsrlq \$26, $r0, $r1
++ vpand .LandMask(%rip), $r0, $r0
++ vpsrlq \$26, $r1, $r2
++ vpand .LandMask(%rip), $r1, $r1
++ vpsllq \$12, $T0, $T1
++ vpxor $T1, $r2, $r2
++ vpsrlq \$26, $r2, $r3
++ vpsrlq \$40, $T0, $r4
++ vpand .LandMask(%rip), $r2, $r2
++ vpand .LandMask(%rip), $r3, $r3
++
++ # SQR R
++ vpmuludq $r0, $r0, $A0
++ vpmuludq $r1, $r0, $A1
++ vpmuludq $r2, $r0, $A2
++ vpmuludq $r3, $r0, $A3
++ vpmuludq $r4, $r0, $A4
++
++ vpsllq \$1, $A1, $A1
++ vpsllq \$1, $A2, $A2
++ vpmuludq $r1, $r1, $T0
++ vpaddq $T0, $A2, $A2
++ vpmuludq $r2, $r1, $T0
++ vpaddq $T0, $A3, $A3
++ vpmuludq $r3, $r1, $T0
++ vpaddq $T0, $A4, $A4
++ vpmuludq $r4, $r1, $A5
++
++ vpsllq \$1, $A3, $A3
++ vpsllq \$1, $A4, $A4
++ vpmuludq $r2, $r2, $T0
++ vpaddq $T0, $A4, $A4
++ vpmuludq $r3, $r2, $T0
++ vpaddq $T0, $A5, $A5
++ vpmuludq $r4, $r2, $A6
++
++ vpsllq \$1, $A5, $A5
++ vpsllq \$1, $A6, $A6
++ vpmuludq $r3, $r3, $T0
++ vpaddq $T0, $A6, $A6
++ vpmuludq $r4, $r3, $A7
++
++ vpsllq \$1, $A7, $A7
++ vpmuludq $r4, $r4, $A8
++
++ # Reduce
++ vpsrlq \$26, $A4, $T0
++ vpand .LandMask(%rip), $A4, $A4
++ vpaddq $T0, $A5, $A5
++
++ vpsllq \$2, $A5, $T0
++ vpaddq $T0, $A5, $A5
++ vpsllq \$2, $A6, $T0
++ vpaddq $T0, $A6, $A6
++ vpsllq \$2, $A7, $T0
++ vpaddq $T0, $A7, $A7
++ vpsllq \$2, $A8, $T0
++ vpaddq $T0, $A8, $A8
++
++ vpaddq $A5, $A0, $A0
++ vpaddq $A6, $A1, $A1
++ vpaddq $A7, $A2, $A2
++ vpaddq $A8, $A3, $A3
++
++ vpsrlq \$26, $A0, $T0
++ vpand .LandMask(%rip), $A0, $A0
++ vpaddq $T0, $A1, $A1
++ vpsrlq \$26, $A1, $T0
++ vpand .LandMask(%rip), $A1, $A1
++ vpaddq $T0, $A2, $A2
++ vpsrlq \$26, $A2, $T0
++ vpand .LandMask(%rip), $A2, $A2
++ vpaddq $T0, $A3, $A3
++ vpsrlq \$26, $A3, $T0
++ vpand .LandMask(%rip), $A3, $A3
++ vpaddq $T0, $A4, $A4
++
++ vpunpcklqdq $r0, $A0, $r0
++ vpunpcklqdq $r1, $A1, $r1
++ vpunpcklqdq $r2, $A2, $r2
++ vpunpcklqdq $r3, $A3, $r3
++ vpunpcklqdq $r4, $A4, $r4
++
++ vmovdqu $r0, $_r0_($state)
++ vmovdqu $r1, $_r1_($state)
++ vmovdqu $r2, $_r2_($state)
++ vmovdqu $r3, $_r3_($state)
++ vmovdqu $r4, $_r4_($state)
++
++ vpsllq \$2, $r1, $A1
++ vpsllq \$2, $r2, $A2
++ vpsllq \$2, $r3, $A3
++ vpsllq \$2, $r4, $A4
++
++ vpaddq $A1, $r1, $A1
++ vpaddq $A2, $r2, $A2
++ vpaddq $A3, $r3, $A3
++ vpaddq $A4, $r4, $A4
++
++ vmovdqu $A1, $_r1_x5($state)
++ vmovdqu $A2, $_r2_x5($state)
++ vmovdqu $A3, $_r3_x5($state)
++ vmovdqu $A4, $_r4_x5($state)
++ # Store k
++ vmovdqu 16*1($key), $T0
++ vmovdqu $T0, $_k_($state)
++ # Init the MAC value
++ vpxor $T0, $T0, $T0
++ vmovdqu $T0, $_A0_($state)
++ vmovd $T0, $_A4_($state)
++ vzeroupper
++ ret
++.size poly1305_init_avx,.-poly1305_init_avx
++___
++}
++
++{
++
++my ($A0, $A1, $A2, $A3, $A4,
++ $T0, $T1, $R0, $R1, $R2,
++ $R3, $R4, $AND_MASK)=map("%xmm$_",(0..12));
++
++my ($state, $in, $in_len)=("%rdi", "%rsi", "%rdx");
++
++$code.=<<___;
++
++###############################################################################
++# void* poly1305_update_avx(void* $state, void* in, uint64_t in_len)
++.globl poly1305_update_avx
++.type poly1305_update_avx, \@function, 2
++.align 64
++poly1305_update_avx:
++
++ vzeroupper
++ vmovd $_A0_($state), $A0
++ vmovd $_A1_($state), $A1
++ vmovd $_A2_($state), $A2
++ vmovd $_A3_($state), $A3
++ vmovd $_A4_($state), $A4
++ vmovdqa .LandMask(%rip), $AND_MASK
++ # Skip to single block case
++ cmp \$32, $in_len
++ jb 3f
++1:
++ cmp \$16*4, $in_len
++ jb 1f
++ sub \$16*2, $in_len
++ # load the next two blocks
++ vmovdqu 16*0($in), $R2
++ vmovdqu 16*1($in), $R3
++ add \$16*2, $in
++
++ vpunpcklqdq $R3, $R2, $R0
++ vpunpckhqdq $R3, $R2, $R1
++
++ vpsrlq \$26, $R0, $R2
++ vpand $AND_MASK, $R0, $R0
++ vpaddq $R0, $A0, $A0
++
++ vpsrlq \$26, $R2, $R0
++ vpand $AND_MASK, $R2, $R2
++ vpaddq $R2, $A1, $A1
++
++ vpsllq \$12, $R1, $R2
++ vpxor $R2, $R0, $R0
++ vpand $AND_MASK, $R0, $R0
++ vpaddq $R0, $A2, $A2
++
++ vpsrlq \$26, $R2, $R0
++ vpsrlq \$40, $R1, $R2
++ vpand $AND_MASK, $R0, $R0
++ vpxor .LsetBit(%rip), $R2, $R2
++ vpaddq $R0, $A3, $A3
++ vpaddq $R2, $A4, $A4
++
++ # Multiply input by R[0]
++ vbroadcastss $_r0_($state), $T0
++ vpmuludq $T0, $A0, $R0
++ vpmuludq $T0, $A1, $R1
++ vpmuludq $T0, $A2, $R2
++ vpmuludq $T0, $A3, $R3
++ vpmuludq $T0, $A4, $R4
++ # Multiply input by R[1] (and R[1]*5)
++ vbroadcastss $_r1_x5($state), $T0
++ vpmuludq $T0, $A4, $T1
++ vpaddq $T1, $R0, $R0
++ vbroadcastss $_r1_($state), $T0
++ vpmuludq $T0, $A0, $T1
++ vpaddq $T1, $R1, $R1
++ vpmuludq $T0, $A1, $T1
++ vpaddq $T1, $R2, $R2
++ vpmuludq $T0, $A2, $T1
++ vpaddq $T1, $R3, $R3
++ vpmuludq $T0, $A3, $T1
++ vpaddq $T1, $R4, $R4
++ # Etc
++ vbroadcastss $_r2_x5($state), $T0
++ vpmuludq $T0, $A3, $T1
++ vpaddq $T1, $R0, $R0
++ vpmuludq $T0, $A4, $T1
++ vpaddq $T1, $R1, $R1
++ vbroadcastss $_r2_($state), $T0
++ vpmuludq $T0, $A0, $T1
++ vpaddq $T1, $R2, $R2
++ vpmuludq $T0, $A1, $T1
++ vpaddq $T1, $R3, $R3
++ vpmuludq $T0, $A2, $T1
++ vpaddq $T1, $R4, $R4
++
++ vbroadcastss $_r3_x5($state), $T0
++ vpmuludq $T0, $A2, $T1
++ vpaddq $T1, $R0, $R0
++ vpmuludq $T0, $A3, $T1
++ vpaddq $T1, $R1, $R1
++ vpmuludq $T0, $A4, $T1
++ vpaddq $T1, $R2, $R2
++ vbroadcastss $_r3_($state), $T0
++ vpmuludq $T0, $A0, $T1
++ vpaddq $T1, $R3, $R3
++ vpmuludq $T0, $A1, $T1
++ vpaddq $T1, $R4, $R4
++
++ vbroadcastss $_r4_x5($state), $T0
++ vpmuludq $T0, $A1, $T1
++ vpaddq $T1, $R0, $R0
++ vpmuludq $T0, $A2, $T1
++ vpaddq $T1, $R1, $R1
++ vpmuludq $T0, $A3, $T1
++ vpaddq $T1, $R2, $R2
++ vpmuludq $T0, $A4, $T1
++ vpaddq $T1, $R3, $R3
++ vbroadcastss $_r4_($state), $T0
++ vpmuludq $T0, $A0, $T1
++ vpaddq $T1, $R4, $R4
++ # Reduce
++ vpsrlq \$26, $R3, $T0
++ vpaddq $T0, $R4, $R4
++ vpand $AND_MASK, $R3, $R3
++
++ vpsrlq \$26, $R4, $T0
++ vpsllq \$2, $T0, $T1
++ vpaddq $T1, $T0, $T0
++ vpaddq $T0, $R0, $R0
++ vpand $AND_MASK, $R4, $R4
++
++ vpsrlq \$26, $R0, $T0
++ vpand $AND_MASK, $R0, $A0
++ vpaddq $T0, $R1, $R1
++ vpsrlq \$26, $R1, $T0
++ vpand $AND_MASK, $R1, $A1
++ vpaddq $T0, $R2, $R2
++ vpsrlq \$26, $R2, $T0
++ vpand $AND_MASK, $R2, $A2
++ vpaddq $T0, $R3, $R3
++ vpsrlq \$26, $R3, $T0
++ vpand $AND_MASK, $R3, $A3
++ vpaddq $T0, $R4, $A4
++ jmp 1b
++1:
++ cmp \$16*2, $in_len
++ jb 1f
++ sub \$16*2, $in_len
++ # load the next two blocks
++ vmovdqu 16*0($in), $R2
++ vmovdqu 16*1($in), $R3
++ add \$16*2, $in
++
++ vpunpcklqdq $R3, $R2, $R0
++ vpunpckhqdq $R3, $R2, $R1
++
++ vpsrlq \$26, $R0, $R2
++ vpand $AND_MASK, $R0, $R0
++ vpaddq $R0, $A0, $A0
++
++ vpsrlq \$26, $R2, $R0
++ vpand $AND_MASK, $R2, $R2
++ vpaddq $R2, $A1, $A1
++
++ vpsllq \$12, $R1, $R2
++ vpxor $R2, $R0, $R0
++ vpand $AND_MASK, $R0, $R0
++ vpaddq $R0, $A2, $A2
++
++ vpsrlq \$26, $R2, $R0
++ vpsrlq \$40, $R1, $R2
++ vpand $AND_MASK, $R0, $R0
++ vpxor .LsetBit(%rip), $R2, $R2
++ vpaddq $R0, $A3, $A3
++ vpaddq $R2, $A4, $A4
++
++ # Multiply input by R[0]
++ vmovdqu $_r0_($state), $T0
++ vpmuludq $T0, $A0, $R0
++ vpmuludq $T0, $A1, $R1
++ vpmuludq $T0, $A2, $R2
++ vpmuludq $T0, $A3, $R3
++ vpmuludq $T0, $A4, $R4
++ # Multiply input by R[1] (and R[1]*5)
++ vmovdqu $_r1_x5($state), $T0
++ vpmuludq $T0, $A4, $T1
++ vpaddq $T1, $R0, $R0
++ vmovdqu $_r1_($state), $T0
++ vpmuludq $T0, $A0, $T1
++ vpaddq $T1, $R1, $R1
++ vpmuludq $T0, $A1, $T1
++ vpaddq $T1, $R2, $R2
++ vpmuludq $T0, $A2, $T1
++ vpaddq $T1, $R3, $R3
++ vpmuludq $T0, $A3, $T1
++ vpaddq $T1, $R4, $R4
++ # Etc
++ vmovdqu $_r2_x5($state), $T0
++ vpmuludq $T0, $A3, $T1
++ vpaddq $T1, $R0, $R0
++ vpmuludq $T0, $A4, $T1
++ vpaddq $T1, $R1, $R1
++ vmovdqu $_r2_($state), $T0
++ vpmuludq $T0, $A0, $T1
++ vpaddq $T1, $R2, $R2
++ vpmuludq $T0, $A1, $T1
++ vpaddq $T1, $R3, $R3
++ vpmuludq $T0, $A2, $T1
++ vpaddq $T1, $R4, $R4
++
++ vmovdqu $_r3_x5($state), $T0
++ vpmuludq $T0, $A2, $T1
++ vpaddq $T1, $R0, $R0
++ vpmuludq $T0, $A3, $T1
++ vpaddq $T1, $R1, $R1
++ vpmuludq $T0, $A4, $T1
++ vpaddq $T1, $R2, $R2
++ vmovdqu $_r3_($state), $T0
++ vpmuludq $T0, $A0, $T1
++ vpaddq $T1, $R3, $R3
++ vpmuludq $T0, $A1, $T1
++ vpaddq $T1, $R4, $R4
++
++ vmovdqu $_r4_x5($state), $T0
++ vpmuludq $T0, $A1, $T1
++ vpaddq $T1, $R0, $R0
++ vpmuludq $T0, $A2, $T1
++ vpaddq $T1, $R1, $R1
++ vpmuludq $T0, $A3, $T1
++ vpaddq $T1, $R2, $R2
++ vpmuludq $T0, $A4, $T1
++ vpaddq $T1, $R3, $R3
++ vmovdqu $_r4_($state), $T0
++ vpmuludq $T0, $A0, $T1
++ vpaddq $T1, $R4, $R4
++1:
++ vpsrldq \$8, $R0, $A0
++ vpsrldq \$8, $R1, $A1
++ vpsrldq \$8, $R2, $A2
++ vpsrldq \$8, $R3, $A3
++ vpsrldq \$8, $R4, $A4
++
++ vpaddq $R0, $A0, $A0
++ vpaddq $R1, $A1, $A1
++ vpaddq $R2, $A2, $A2
++ vpaddq $R3, $A3, $A3
++ vpaddq $R4, $A4, $A4
++ # Reduce
++ vpsrlq \$26, $A3, $T0
++ vpaddq $T0, $A4, $A4
++ vpand $AND_MASK, $A3, $A3
++ vpsrlq \$26, $A4, $T0
++ vpsllq \$2, $T0, $T1
++ vpaddq $T1, $T0, $T0
++ vpaddq $T0, $A0, $A0
++ vpand $AND_MASK, $A4, $A4
++ vpsrlq \$26, $A0, $T0
++ vpand $AND_MASK, $A0, $A0
++ vpaddq $T0, $A1, $A1
++ vpsrlq \$26, $A1, $T0
++ vpand $AND_MASK, $A1, $A1
++ vpaddq $T0, $A2, $A2
++ vpsrlq \$26, $A2, $T0
++ vpand $AND_MASK, $A2, $A2
++ vpaddq $T0, $A3, $A3
++ vpsrlq \$26, $A3, $T0
++ vpand $AND_MASK, $A3, $A3
++ vpaddq $T0, $A4, $A4
++3:
++ cmp \$16, $in_len
++ jb 1f
++
++ # load the next block
++ vmovq 8*0($in), $R0
++ vmovq 8*1($in), $R1
++ add \$16, $in
++ sub \$16, $in_len
++
++ vpsrlq \$26, $R0, $R2
++ vpand $AND_MASK, $R0, $R0
++ vpaddq $R0, $A0, $A0
++
++ vpsrlq \$26, $R2, $R0
++ vpand $AND_MASK, $R2, $R2
++ vpaddq $R2, $A1, $A1
++
++ vpsllq \$12, $R1, $R2
++ vpxor $R2, $R0, $R0
++ vpand $AND_MASK, $R0, $R0
++ vpaddq $R0, $A2, $A2
++
++ vpsrlq \$26, $R2, $R0
++ vpsrlq \$40, $R1, $R2
++ vpand $AND_MASK, $R0, $R0
++ vpxor .LsetBit(%rip), $R2, $R2
++ vpaddq $R0, $A3, $A3
++ vpaddq $R2, $A4, $A4
++2:
++ # Multiply input by R[0]
++ vmovq $_r0_+8($state), $T0
++ vpmuludq $T0, $A0, $R0
++ vpmuludq $T0, $A1, $R1
++ vpmuludq $T0, $A2, $R2
++ vpmuludq $T0, $A3, $R3
++ vpmuludq $T0, $A4, $R4
++ # Multiply input by R[1] (and R[1]*5)
++ vmovq $_r1_x5+8($state), $T0
++ vpmuludq $T0, $A4, $T1
++ vpaddq $T1, $R0, $R0
++ vmovq $_r1_+8($state), $T0
++ vpmuludq $T0, $A0, $T1
++ vpaddq $T1, $R1, $R1
++ vpmuludq $T0, $A1, $T1
++ vpaddq $T1, $R2, $R2
++ vpmuludq $T0, $A2, $T1
++ vpaddq $T1, $R3, $R3
++ vpmuludq $T0, $A3, $T1
++ vpaddq $T1, $R4, $R4
++ # Etc
++ vmovq $_r2_x5+8($state), $T0
++ vpmuludq $T0, $A3, $T1
++ vpaddq $T1, $R0, $R0
++ vpmuludq $T0, $A4, $T1
++ vpaddq $T1, $R1, $R1
++ vmovq $_r2_+8($state), $T0
++ vpmuludq $T0, $A0, $T1
++ vpaddq $T1, $R2, $R2
++ vpmuludq $T0, $A1, $T1
++ vpaddq $T1, $R3, $R3
++ vpmuludq $T0, $A2, $T1
++ vpaddq $T1, $R4, $R4
++
++ vmovq $_r3_x5+8($state), $T0
++ vpmuludq $T0, $A2, $T1
++ vpaddq $T1, $R0, $R0
++ vpmuludq $T0, $A3, $T1
++ vpaddq $T1, $R1, $R1
++ vpmuludq $T0, $A4, $T1
++ vpaddq $T1, $R2, $R2
++ vmovq $_r3_+8($state), $T0
++ vpmuludq $T0, $A0, $T1
++ vpaddq $T1, $R3, $R3
++ vpmuludq $T0, $A1, $T1
++ vpaddq $T1, $R4, $R4
++
++ vmovq $_r4_x5+8($state), $T0
++ vpmuludq $T0, $A1, $T1
++ vpaddq $T1, $R0, $R0
++ vpmuludq $T0, $A2, $T1
++ vpaddq $T1, $R1, $R1
++ vpmuludq $T0, $A3, $T1
++ vpaddq $T1, $R2, $R2
++ vpmuludq $T0, $A4, $T1
++ vpaddq $T1, $R3, $R3
++ vmovq $_r4_+8($state), $T0
++ vpmuludq $T0, $A0, $T1
++ vpaddq $T1, $R4, $R4
++
++ # Reduce
++ vpsrlq \$26, $R3, $T0
++ vpaddq $T0, $R4, $R4
++ vpand $AND_MASK, $R3, $R3
++ vpsrlq \$26, $R4, $T0
++ vpsllq \$2, $T0, $T1
++ vpaddq $T1, $T0, $T0
++ vpaddq $T0, $R0, $R0
++ vpand $AND_MASK, $R4, $R4
++ vpsrlq \$26, $R0, $T0
++ vpand $AND_MASK, $R0, $A0
++ vpaddq $T0, $R1, $R1
++ vpsrlq \$26, $R1, $T0
++ vpand $AND_MASK, $R1, $A1
++ vpaddq $T0, $R2, $R2
++ vpsrlq \$26, $R2, $T0
++ vpand $AND_MASK, $R2, $A2
++ vpaddq $T0, $R3, $R3
++ vpsrlq \$26, $R3, $T0
++ vpand $AND_MASK, $R3, $A3
++ vpaddq $T0, $R4, $A4
++
++1:
++ test $in_len, $in_len
++ jz 1f
++
++ vmovdqa .Lone(%rip), $R0
++3:
++ dec $in_len
++ vpslldq \$1, $R0, $R0
++ vpinsrb \$0, ($in, $in_len), $R0, $R0
++ test $in_len, $in_len
++ jnz 3b
++
++ vpsrldq \$8, $R0, $R1
++ vpsrlq \$26, $R0, $R2
++ vpand $AND_MASK, $R0, $R0
++ vpaddq $R0, $A0, $A0
++
++ vpsrlq \$26, $R2, $R0
++ vpand $AND_MASK, $R2, $R2
++ vpaddq $R2, $A1, $A1
++
++ vpsllq \$12, $R1, $R2
++ vpxor $R2, $R0, $R0
++ vpand $AND_MASK, $R0, $R0
++ vpaddq $R0, $A2, $A2
++
++ vpsrlq \$26, $R2, $R0
++ vpsrlq \$40, $R1, $R2
++ vpand $AND_MASK, $R0, $R0
++ vpaddq $R0, $A3, $A3
++ vpaddq $R2, $A4, $A4
++ xor $in_len, $in_len
++ jmp 2b
++1:
++ vmovd $A0, $_A0_($state)
++ vmovd $A1, $_A1_($state)
++ vmovd $A2, $_A2_($state)
++ vmovd $A3, $_A3_($state)
++ vmovd $A4, $_A4_($state)
++
++
++ mov $in, %rax
++ vzeroupper
++ ret
++.size poly1305_update_avx,.-poly1305_update_avx
++###############################################################################
++# void poly1305_finish_avx(void* $state, uint64_t mac[2]);
++.type poly1305_finish_avx,\@function, 2
++.globl poly1305_finish_avx
++poly1305_finish_avx:
++___
++my $mac="%rsi";
++$code.=<<___;
++ vzeroupper
++ vmovd $_A0_($state), $A0
++ vmovd $_A1_($state), $A1
++ vmovd $_A2_($state), $A2
++ vmovd $_A3_($state), $A3
++ vmovd $_A4_($state), $A4
++ # Reduce one last time in case there was a carry from 130 bit
++ vpsrlq \$26, $A4, $T0
++ vpsllq \$2, $T0, $T1
++ vpaddq $T1, $T0, $T0
++ vpaddq $T0, $A0, $A0
++ vpand .LandMask(%rip), $A4, $A4
++
++ vpsrlq \$26, $A0, $T0
++ vpand .LandMask(%rip), $A0, $A0
++ vpaddq $T0, $A1, $A1
++ vpsrlq \$26, $A1, $T0
++ vpand .LandMask(%rip), $A1, $A1
++ vpaddq $T0, $A2, $A2
++ vpsrlq \$26, $A2, $T0
++ vpand .LandMask(%rip), $A2, $A2
++ vpaddq $T0, $A3, $A3
++ vpsrlq \$26, $A3, $T0
++ vpand .LandMask(%rip), $A3, $A3
++ vpaddq $T0, $A4, $A4
++ # Convert to normal
++ vpsllq \$26, $A1, $T0
++ vpxor $T0, $A0, $A0
++ vpsllq \$52, $A2, $T0
++ vpxor $T0, $A0, $A0
++ vpsrlq \$12, $A2, $A1
++ vpsllq \$14, $A3, $T0
++ vpxor $T0, $A1, $A1
++ vpsllq \$40, $A4, $T0
++ vpxor $T0, $A1, $A1
++ vmovq $A0, %rax
++ vmovq $A1, %rdx
++
++ add $_k_($state), %rax
++ adc $_k_+8($state), %rdx
++ mov %rax, ($mac)
++ mov %rdx, 8($mac)
++ vzeroupper
++ ret
++.size poly1305_finish_avx,.-poly1305_finish_avx
++___
++}
++}}
++
++$code =~ s/\`([^\`]*)\`/eval($1)/gem;
++print $code;
++close STDOUT;
+diff --git a/crypto/chacha20poly1305/asm/poly1305_avx2.pl b/crypto/chacha20poly1305/asm/poly1305_avx2.pl
+new file mode 100644
+index 0000000..8134542
+--- /dev/null
++++ b/crypto/chacha20poly1305/asm/poly1305_avx2.pl
+@@ -0,0 +1,918 @@
++##############################################################################
++# #
++# Copyright 2014 Intel Corporation #
++# #
++# Licensed under the Apache License, Version 2.0 (the "License"); #
++# you may not use this file except in compliance with the License. #
++# You may obtain a copy of the License at #
++# #
++# http://www.apache.org/licenses/LICENSE-2.0 #
++# #
++# Unless required by applicable law or agreed to in writing, software #
++# distributed under the License is distributed on an "AS IS" BASIS, #
++# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
++# See the License for the specific language governing permissions and #
++# limitations under the License. #
++# #
++##############################################################################
++# #
++# Developers and authors: #
++# Shay Gueron (1, 2), and Vlad Krasnov (1) #
++# (1) Intel Corporation, Israel Development Center #
++# (2) University of Haifa #
++# #
++##############################################################################
++# state:
++# 0: r[0] || r^2[0]
++# 16: r[1] || r^2[1]
++# 32: r[2] || r^2[2]
++# 48: r[3] || r^2[3]
++# 64: r[4] || r^2[4]
++# 80: r[1]*5 || r^2[1]*5
++# 96: r[2]*5 || r^2[2]*5
++#112: r[3]*5 || r^2[3]*5
++#128: r[4]*5 || r^2[4]*5
++#144: k
++#160: A0
++#164: A1
++#168: A2
++#172: A3
++#176: A4
++#180: END
++
++$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";
++
++open OUT,"| \"$^X\" $xlate $flavour $output";
++*STDOUT=*OUT;
++
++if (`$ENV{CC} -Wa,-v -c -o /dev/null -x assembler /dev/null 2>&1`
++ =~ /GNU assembler version ([2-9]\.[0-9]+)/) {
++ $avx = ($1>=2.19) + ($1>=2.22);
++}
++
++if ($win64 && ($flavour =~ /nasm/ || $ENV{ASM} =~ /nasm/) &&
++ `nasm -v 2>&1` =~ /NASM version ([2-9]\.[0-9]+)/) {
++ $avx = ($1>=2.09) + ($1>=2.10);
++}
++
++if ($win64 && ($flavour =~ /masm/ || $ENV{ASM} =~ /ml64/) &&
++ `ml64 2>&1` =~ /Version ([0-9]+)\./) {
++ $avx = ($1>=10) + ($1>=11);
++}
++
++if (`$ENV{CC} -v 2>&1` =~ /(^clang version|based on LLVM) ([3-9])\.([0-9]+)/) {
++ my $ver = $2 + $3/100.0; # 3.1->3.01, 3.10->3.10
++ $avx = ($ver>=3.0) + ($ver>=3.01);
++}
++
++if ($avx>=1) {{
++
++my ($_r0_, $_r1_, $_r2_, $_r3_, $_r4_, $_r1_x5, $_r2_x5, $_r3_x5, $_r4_x5, $_k_, $_A0_, $_A1_, $_A2_, $_A3_, $_A4_)
++= (0,32,64,96,128,160,192,224,256,288,304,308,312,316,320);
++
++$code.=<<___;
++.text
++.align 32
++.LandMask:
++.quad 0x3FFFFFF, 0x3FFFFFF, 0x3FFFFFF, 0x3FFFFFF
++.LsetBit:
++.quad 0x1000000, 0x1000000, 0x1000000, 0x1000000
++.LrSet:
++.quad 0xFFFFFFC0FFFFFFF, 0xFFFFFFC0FFFFFFF, 0xFFFFFFC0FFFFFFF, 0xFFFFFFC0FFFFFFF
++.quad 0xFFFFFFC0FFFFFFC, 0xFFFFFFC0FFFFFFC, 0xFFFFFFC0FFFFFFC, 0xFFFFFFC0FFFFFFC
++
++.LpermFix:
++.long 6,7,6,7,6,7,6,7
++.long 4,5,6,7,6,7,6,7
++.long 2,3,6,7,4,5,6,7
++.long 0,1,4,5,2,3,6,7
++___
++
++
++{
++my ($A0, $A1, $A2, $A3, $A4,
++ $r0, $r1, $r2, $r3, $r4,
++ $T0, $T1, $A5, $A6, $A7, $A8)=map("%xmm$_",(0..15));
++my ($A0_y, $A1_y, $A2_y, $A3_y, $A4_y,
++ $r0_y, $r1_y, $r2_y, $r3_y, $r4_y)=map("%ymm$_",(0..9));
++my ($state, $key)
++ =("%rdi", "%rsi");
++
++$code.=<<___;
++################################################################################
++# void poly1305_init_avx2(void *state, uint8_t key[32])
++
++.globl poly1305_init_avx2
++.type poly1305_init_avx2, \@function, 2
++.align 64
++poly1305_init_avx2:
++ vzeroupper
++
++ # Store k
++ vmovdqu 16*1($key), $T0
++ vmovdqu $T0, $_k_($state)
++ # Init the MAC value
++ vpxor $T0, $T0, $T0
++ vmovdqu $T0, $_A0_($state)
++ vmovd $T0, $_A4_($state)
++ # load and convert r
++ vmovq 8*0($key), $r0
++ vmovq 8*1($key), $T0
++ vpand .LrSet(%rip), $r0, $r0
++ vpand .LrSet+32(%rip), $T0, $T0
++
++ vpsrlq \$26, $r0, $r1
++ vpand .LandMask(%rip), $r0, $r0
++ vpsrlq \$26, $r1, $r2
++ vpand .LandMask(%rip), $r1, $r1
++ vpsllq \$12, $T0, $T1
++ vpxor $T1, $r2, $r2
++ vpsrlq \$26, $r2, $r3
++ vpsrlq \$40, $T0, $r4
++ vpand .LandMask(%rip), $r2, $r2
++ vpand .LandMask(%rip), $r3, $r3
++ # SQR R
++ vpmuludq $r0, $r0, $A0
++ vpmuludq $r1, $r0, $A1
++ vpmuludq $r2, $r0, $A2
++ vpmuludq $r3, $r0, $A3
++ vpmuludq $r4, $r0, $A4
++
++ vpsllq \$1, $A1, $A1
++ vpsllq \$1, $A2, $A2
++ vpmuludq $r1, $r1, $T0
++ vpaddq $T0, $A2, $A2
++ vpmuludq $r2, $r1, $T0
++ vpaddq $T0, $A3, $A3
++ vpmuludq $r3, $r1, $T0
++ vpaddq $T0, $A4, $A4
++ vpmuludq $r4, $r1, $A5
++
++ vpsllq \$1, $A3, $A3
++ vpsllq \$1, $A4, $A4
++ vpmuludq $r2, $r2, $T0
++ vpaddq $T0, $A4, $A4
++ vpmuludq $r3, $r2, $T0
++ vpaddq $T0, $A5, $A5
++ vpmuludq $r4, $r2, $A6
++
++ vpsllq \$1, $A5, $A5
++ vpsllq \$1, $A6, $A6
++ vpmuludq $r3, $r3, $T0
++ vpaddq $T0, $A6, $A6
++ vpmuludq $r4, $r3, $A7
++
++ vpsllq \$1, $A7, $A7
++ vpmuludq $r4, $r4, $A8
++
++ # Reduce
++ vpsrlq \$26, $A4, $T0
++ vpand .LandMask(%rip), $A4, $A4
++ vpaddq $T0, $A5, $A5
++
++ vpsllq \$2, $A5, $T0
++ vpaddq $T0, $A5, $A5
++ vpsllq \$2, $A6, $T0
++ vpaddq $T0, $A6, $A6
++ vpsllq \$2, $A7, $T0
++ vpaddq $T0, $A7, $A7
++ vpsllq \$2, $A8, $T0
++ vpaddq $T0, $A8, $A8
++
++ vpaddq $A5, $A0, $A0
++ vpaddq $A6, $A1, $A1
++ vpaddq $A7, $A2, $A2
++ vpaddq $A8, $A3, $A3
++
++ vpsrlq \$26, $A0, $T0
++ vpand .LandMask(%rip), $A0, $A0
++ vpaddq $T0, $A1, $A1
++ vpsrlq \$26, $A1, $T0
++ vpand .LandMask(%rip), $A1, $A1
++ vpaddq $T0, $A2, $A2
++ vpsrlq \$26, $A2, $T0
++ vpand .LandMask(%rip), $A2, $A2
++ vpaddq $T0, $A3, $A3
++ vpsrlq \$26, $A3, $T0
++ vpand .LandMask(%rip), $A3, $A3
++ vpaddq $T0, $A4, $A4
++
++ vpunpcklqdq $r0, $A0, $r0
++ vpunpcklqdq $r1, $A1, $r1
++ vpunpcklqdq $r2, $A2, $r2
++ vpunpcklqdq $r3, $A3, $r3
++ vpunpcklqdq $r4, $A4, $r4
++
++ vmovdqu $r0, $_r0_+16($state)
++ vmovdqu $r1, $_r1_+16($state)
++ vmovdqu $r2, $_r2_+16($state)
++ vmovdqu $r3, $_r3_+16($state)
++ vmovdqu $r4, $_r4_+16($state)
++
++ vpsllq \$2, $r1, $A1
++ vpsllq \$2, $r2, $A2
++ vpsllq \$2, $r3, $A3
++ vpsllq \$2, $r4, $A4
++
++ vpaddq $A1, $r1, $A1
++ vpaddq $A2, $r2, $A2
++ vpaddq $A3, $r3, $A3
++ vpaddq $A4, $r4, $A4
++
++ vmovdqu $A1, $_r1_x5+16($state)
++ vmovdqu $A2, $_r2_x5+16($state)
++ vmovdqu $A3, $_r3_x5+16($state)
++ vmovdqu $A4, $_r4_x5+16($state)
++
++ # Compute r^3 and r^4
++ vpshufd \$0x44, $r0, $A0
++ vpshufd \$0x44, $r1, $A1
++ vpshufd \$0x44, $r2, $A2
++ vpshufd \$0x44, $r3, $A3
++ vpshufd \$0x44, $r4, $A4
++
++ # Multiply input by R[0]
++ vmovdqu $_r0_+16($state), $T0
++ vpmuludq $T0, $A0, $r0
++ vpmuludq $T0, $A1, $r1
++ vpmuludq $T0, $A2, $r2
++ vpmuludq $T0, $A3, $r3
++ vpmuludq $T0, $A4, $r4
++ # Multiply input by R[1] (and R[1]*5)
++ vmovdqu $_r1_x5+16($state), $T0
++ vpmuludq $T0, $A4, $T1
++ vpaddq $T1, $r0, $r0
++ vmovdqu $_r1_+16($state), $T0
++ vpmuludq $T0, $A0, $T1
++ vpaddq $T1, $r1, $r1
++ vpmuludq $T0, $A1, $T1
++ vpaddq $T1, $r2, $r2
++ vpmuludq $T0, $A2, $T1
++ vpaddq $T1, $r3, $r3
++ vpmuludq $T0, $A3, $T1
++ vpaddq $T1, $r4, $r4
++ # Etc
++ vmovdqu $_r2_x5+16($state), $T0
++ vpmuludq $T0, $A3, $T1
++ vpaddq $T1, $r0, $r0
++ vpmuludq $T0, $A4, $T1
++ vpaddq $T1, $r1, $r1
++ vmovdqu $_r2_+16($state), $T0
++ vpmuludq $T0, $A0, $T1
++ vpaddq $T1, $r2, $r2
++ vpmuludq $T0, $A1, $T1
++ vpaddq $T1, $r3, $r3
++ vpmuludq $T0, $A2, $T1
++ vpaddq $T1, $r4, $r4
++
++ vmovdqu $_r3_x5+16($state), $T0
++ vpmuludq $T0, $A2, $T1
++ vpaddq $T1, $r0, $r0
++ vpmuludq $T0, $A3, $T1
++ vpaddq $T1, $r1, $r1
++ vpmuludq $T0, $A4, $T1
++ vpaddq $T1, $r2, $r2
++ vmovdqu $_r3_+16($state), $T0
++ vpmuludq $T0, $A0, $T1
++ vpaddq $T1, $r3, $r3
++ vpmuludq $T0, $A1, $T1
++ vpaddq $T1, $r4, $r4
++
++ vmovdqu $_r4_x5+16($state), $T0
++ vpmuludq $T0, $A1, $T1
++ vpaddq $T1, $r0, $r0
++ vpmuludq $T0, $A2, $T1
++ vpaddq $T1, $r1, $r1
++ vpmuludq $T0, $A3, $T1
++ vpaddq $T1, $r2, $r2
++ vpmuludq $T0, $A4, $T1
++ vpaddq $T1, $r3, $r3
++ vmovdqu $_r4_+16($state), $T0
++ vpmuludq $T0, $A0, $T1
++ vpaddq $T1, $r4, $r4
++ # Reduce
++ vpsrlq \$26, $r3, $T0
++ vpaddq $T0, $r4, $r4
++ vpand .LandMask(%rip), $r3, $r3
++ vpsrlq \$26, $r4, $T0
++ vpsllq \$2, $T0, $T1
++ vpaddq $T1, $T0, $T0
++ vpaddq $T0, $r0, $r0
++ vpand .LandMask(%rip), $r4, $r4
++ vpsrlq \$26, $r0, $T0
++ vpand .LandMask(%rip), $r0, $r0
++ vpaddq $T0, $r1, $r1
++ vpsrlq \$26, $r1, $T0
++ vpand .LandMask(%rip), $r1, $r1
++ vpaddq $T0, $r2, $r2
++ vpsrlq \$26, $r2, $T0
++ vpand .LandMask(%rip), $r2, $r2
++ vpaddq $T0, $r3, $r3
++ vpsrlq \$26, $r3, $T0
++ vpand .LandMask(%rip), $r3, $r3
++ vpaddq $T0, $r4, $r4
++
++ vmovdqu $r0, $_r0_($state)
++ vmovdqu $r1, $_r1_($state)
++ vmovdqu $r2, $_r2_($state)
++ vmovdqu $r3, $_r3_($state)
++ vmovdqu $r4, $_r4_($state)
++
++ vpsllq \$2, $r1, $A1
++ vpsllq \$2, $r2, $A2
++ vpsllq \$2, $r3, $A3
++ vpsllq \$2, $r4, $A4
++
++ vpaddq $A1, $r1, $A1
++ vpaddq $A2, $r2, $A2
++ vpaddq $A3, $r3, $A3
++ vpaddq $A4, $r4, $A4
++
++ vmovdqu $A1, $_r1_x5($state)
++ vmovdqu $A2, $_r2_x5($state)
++ vmovdqu $A3, $_r3_x5($state)
++ vmovdqu $A4, $_r4_x5($state)
++
++ ret
++.size poly1305_init_avx2,.-poly1305_init_avx2
++___
++}
++
++{
++
++my ($A0, $A1, $A2, $A3, $A4,
++ $T0, $T1, $R0, $R1, $R2,
++ $R3, $R4, $AND_MASK, $PERM_MASK, $SET_MASK)=map("%ymm$_",(0..14));
++
++my ($A0_x, $A1_x, $A2_x, $A3_x, $A4_x,
++ $T0_x, $T1_x, $R0_x, $R1_x, $R2_x,
++ $R3_x, $R4_x, $AND_MASK_x, $PERM_MASK_x, $SET_MASK_x)=map("%xmm$_",(0..14));
++
++my ($state, $in, $in_len, $hlp, $rsp_save)=("%rdi", "%rsi", "%rdx", "%rcx", "%rax");
++
++$code.=<<___;
++
++###############################################################################
++# void poly1305_update_avx2(void* $state, void* in, uint64_t in_len2)
++.globl poly1305_update_avx2
++.type poly1305_update_avx2, \@function, 2
++.align 64
++poly1305_update_avx2:
++
++ vmovd $_A0_($state), $A0_x
++ vmovd $_A1_($state), $A1_x
++ vmovd $_A2_($state), $A2_x
++ vmovd $_A3_($state), $A3_x
++ vmovd $_A4_($state), $A4_x
++
++ vmovdqa .LandMask(%rip), $AND_MASK
++1:
++ cmp \$32*4, $in_len
++ jb 1f
++ sub \$32*2, $in_len
++
++ # load the next four blocks
++ vmovdqu 32*0($in), $R2
++ vmovdqu 32*1($in), $R3
++ add \$32*2, $in
++
++ vpunpcklqdq $R3, $R2, $R0
++ vpunpckhqdq $R3, $R2, $R1
++
++ vpermq \$0xD8, $R0, $R0 # it is possible to rearrange the precomputations, and save this shuffle
++ vpermq \$0xD8, $R1, $R1
++
++ vpsrlq \$26, $R0, $R2
++ vpand $AND_MASK, $R0, $R0
++ vpaddq $R0, $A0, $A0
++
++ vpsrlq \$26, $R2, $R0
++ vpand $AND_MASK, $R2, $R2
++ vpaddq $R2, $A1, $A1
++
++ vpsllq \$12, $R1, $R2
++ vpxor $R2, $R0, $R0
++ vpand $AND_MASK, $R0, $R0
++ vpaddq $R0, $A2, $A2
++
++ vpsrlq \$26, $R2, $R0
++ vpsrlq \$40, $R1, $R2
++ vpand $AND_MASK, $R0, $R0
++ vpxor .LsetBit(%rip), $R2, $R2
++ vpaddq $R0, $A3, $A3
++ vpaddq $R2, $A4, $A4
++
++ # Multiply input by R[0]
++ vpbroadcastq $_r0_($state), $T0
++ vpmuludq $T0, $A0, $R0
++ vpmuludq $T0, $A1, $R1
++ vpmuludq $T0, $A2, $R2
++ vpmuludq $T0, $A3, $R3
++ vpmuludq $T0, $A4, $R4
++ # Multiply input by R[1] (and R[1]*5)
++ vpbroadcastq $_r1_x5($state), $T0
++ vpmuludq $T0, $A4, $T1
++ vpaddq $T1, $R0, $R0
++ vpbroadcastq $_r1_($state), $T0
++ vpmuludq $T0, $A0, $T1
++ vpaddq $T1, $R1, $R1
++ vpmuludq $T0, $A1, $T1
++ vpaddq $T1, $R2, $R2
++ vpmuludq $T0, $A2, $T1
++ vpaddq $T1, $R3, $R3
++ vpmuludq $T0, $A3, $T1
++ vpaddq $T1, $R4, $R4
++ # Etc
++ vpbroadcastq $_r2_x5($state), $T0
++ vpmuludq $T0, $A3, $T1
++ vpaddq $T1, $R0, $R0
++ vpmuludq $T0, $A4, $T1
++ vpaddq $T1, $R1, $R1
++ vpbroadcastq $_r2_($state), $T0
++ vpmuludq $T0, $A0, $T1
++ vpaddq $T1, $R2, $R2
++ vpmuludq $T0, $A1, $T1
++ vpaddq $T1, $R3, $R3
++ vpmuludq $T0, $A2, $T1
++ vpaddq $T1, $R4, $R4
++
++ vpbroadcastq $_r3_x5($state), $T0
++ vpmuludq $T0, $A2, $T1
++ vpaddq $T1, $R0, $R0
++ vpmuludq $T0, $A3, $T1
++ vpaddq $T1, $R1, $R1
++ vpmuludq $T0, $A4, $T1
++ vpaddq $T1, $R2, $R2
++ vpbroadcastq $_r3_($state), $T0
++ vpmuludq $T0, $A0, $T1
++ vpaddq $T1, $R3, $R3
++ vpmuludq $T0, $A1, $T1
++ vpaddq $T1, $R4, $R4
++
++ vpbroadcastq $_r4_x5($state), $T0
++ vpmuludq $T0, $A1, $T1
++ vpaddq $T1, $R0, $R0
++ vpmuludq $T0, $A2, $T1
++ vpaddq $T1, $R1, $R1
++ vpmuludq $T0, $A3, $T1
++ vpaddq $T1, $R2, $R2
++ vpmuludq $T0, $A4, $T1
++ vpaddq $T1, $R3, $R3
++ vpbroadcastq $_r4_($state), $T0
++ vpmuludq $T0, $A0, $T1
++ vpaddq $T1, $R4, $R4
++ # Reduce
++ vpsrlq \$26, $R3, $T0
++ vpaddq $T0, $R4, $R4
++ vpand $AND_MASK, $R3, $R3
++
++ vpsrlq \$26, $R4, $T0
++ vpsllq \$2, $T0, $T1
++ vpaddq $T1, $T0, $T0
++ vpaddq $T0, $R0, $R0
++ vpand $AND_MASK, $R4, $R4
++
++ vpsrlq \$26, $R0, $T0
++ vpand $AND_MASK, $R0, $A0
++ vpaddq $T0, $R1, $R1
++ vpsrlq \$26, $R1, $T0
++ vpand $AND_MASK, $R1, $A1
++ vpaddq $T0, $R2, $R2
++ vpsrlq \$26, $R2, $T0
++ vpand $AND_MASK, $R2, $A2
++ vpaddq $T0, $R3, $R3
++ vpsrlq \$26, $R3, $T0
++ vpand $AND_MASK, $R3, $A3
++ vpaddq $T0, $R4, $A4
++ jmp 1b
++1:
++
++ cmp \$32*2, $in_len
++ jb 1f
++ sub \$32*2, $in_len
++ # load the next four blocks
++ vmovdqu 32*0($in), $R2
++ vmovdqu 32*1($in), $R3
++ add \$32*2, $in
++
++ vpunpcklqdq $R3, $R2, $R0
++ vpunpckhqdq $R3, $R2, $R1
++
++ vpermq \$0xD8, $R0, $R0
++ vpermq \$0xD8, $R1, $R1
++
++ vpsrlq \$26, $R0, $R2
++ vpand $AND_MASK, $R0, $R0
++ vpaddq $R0, $A0, $A0
++
++ vpsrlq \$26, $R2, $R0
++ vpand $AND_MASK, $R2, $R2
++ vpaddq $R2, $A1, $A1
++
++ vpsllq \$12, $R1, $R2
++ vpxor $R2, $R0, $R0
++ vpand $AND_MASK, $R0, $R0
++ vpaddq $R0, $A2, $A2
++
++ vpsrlq \$26, $R2, $R0
++ vpsrlq \$40, $R1, $R2
++ vpand $AND_MASK, $R0, $R0
++ vpxor .LsetBit(%rip), $R2, $R2
++ vpaddq $R0, $A3, $A3
++ vpaddq $R2, $A4, $A4
++
++ # Multiply input by R[0]
++ vmovdqu $_r0_($state), $T0
++ vpmuludq $T0, $A0, $R0
++ vpmuludq $T0, $A1, $R1
++ vpmuludq $T0, $A2, $R2
++ vpmuludq $T0, $A3, $R3
++ vpmuludq $T0, $A4, $R4
++ # Multiply input by R[1] (and R[1]*5)
++ vmovdqu $_r1_x5($state), $T0
++ vpmuludq $T0, $A4, $T1
++ vpaddq $T1, $R0, $R0
++ vmovdqu $_r1_($state), $T0
++ vpmuludq $T0, $A0, $T1
++ vpaddq $T1, $R1, $R1
++ vpmuludq $T0, $A1, $T1
++ vpaddq $T1, $R2, $R2
++ vpmuludq $T0, $A2, $T1
++ vpaddq $T1, $R3, $R3
++ vpmuludq $T0, $A3, $T1
++ vpaddq $T1, $R4, $R4
++ # Etc
++ vmovdqu $_r2_x5($state), $T0
++ vpmuludq $T0, $A3, $T1
++ vpaddq $T1, $R0, $R0
++ vpmuludq $T0, $A4, $T1
++ vpaddq $T1, $R1, $R1
++ vmovdqu $_r2_($state), $T0
++ vpmuludq $T0, $A0, $T1
++ vpaddq $T1, $R2, $R2
++ vpmuludq $T0, $A1, $T1
++ vpaddq $T1, $R3, $R3
++ vpmuludq $T0, $A2, $T1
++ vpaddq $T1, $R4, $R4
++
++ vmovdqu $_r3_x5($state), $T0
++ vpmuludq $T0, $A2, $T1
++ vpaddq $T1, $R0, $R0
++ vpmuludq $T0, $A3, $T1
++ vpaddq $T1, $R1, $R1
++ vpmuludq $T0, $A4, $T1
++ vpaddq $T1, $R2, $R2
++ vmovdqu $_r3_($state), $T0
++ vpmuludq $T0, $A0, $T1
++ vpaddq $T1, $R3, $R3
++ vpmuludq $T0, $A1, $T1
++ vpaddq $T1, $R4, $R4
++
++ vmovdqu $_r4_x5($state), $T0
++ vpmuludq $T0, $A1, $T1
++ vpaddq $T1, $R0, $R0
++ vpmuludq $T0, $A2, $T1
++ vpaddq $T1, $R1, $R1
++ vpmuludq $T0, $A3, $T1
++ vpaddq $T1, $R2, $R2
++ vpmuludq $T0, $A4, $T1
++ vpaddq $T1, $R3, $R3
++ vmovdqu $_r4_($state), $T0
++ vpmuludq $T0, $A0, $T1
++ vpaddq $T1, $R4, $R4
++ # Reduce
++ vpsrlq \$26, $R3, $T0
++ vpaddq $T0, $R4, $R4
++ vpand $AND_MASK, $R3, $R3
++ vpsrlq \$26, $R4, $T0
++ vpsllq \$2, $T0, $T1
++ vpaddq $T1, $T0, $T0
++ vpaddq $T0, $R0, $R0
++ vpand $AND_MASK, $R4, $R4
++ vpsrlq \$26, $R0, $T0
++ vpand $AND_MASK, $R0, $A0
++ vpaddq $T0, $R1, $R1
++ vpsrlq \$26, $R1, $T0
++ vpand $AND_MASK, $R1, $A1
++ vpaddq $T0, $R2, $R2
++ vpsrlq \$26, $R2, $T0
++ vpand $AND_MASK, $R2, $A2
++ vpaddq $T0, $R3, $R3
++ vpsrlq \$26, $R3, $T0
++ vpand $AND_MASK, $R3, $A3
++ vpaddq $T0, $R4, $A4
++
++ vpsrldq \$8, $A0, $R0
++ vpsrldq \$8, $A1, $R1
++ vpsrldq \$8, $A2, $R2
++ vpsrldq \$8, $A3, $R3
++ vpsrldq \$8, $A4, $R4
++
++ vpaddq $R0, $A0, $A0
++ vpaddq $R1, $A1, $A1
++ vpaddq $R2, $A2, $A2
++ vpaddq $R3, $A3, $A3
++ vpaddq $R4, $A4, $A4
++
++ vpermq \$0xAA, $A0, $R0
++ vpermq \$0xAA, $A1, $R1
++ vpermq \$0xAA, $A2, $R2
++ vpermq \$0xAA, $A3, $R3
++ vpermq \$0xAA, $A4, $R4
++
++ vpaddq $R0, $A0, $A0
++ vpaddq $R1, $A1, $A1
++ vpaddq $R2, $A2, $A2
++ vpaddq $R3, $A3, $A3
++ vpaddq $R4, $A4, $A4
++1:
++ test $in_len, $in_len
++ jz 5f
++ # In case 1,2 or 3 blocks remain, we want to multiply them correctly
++ vmovq $A0_x, $A0_x
++ vmovq $A1_x, $A1_x
++ vmovq $A2_x, $A2_x
++ vmovq $A3_x, $A3_x
++ vmovq $A4_x, $A4_x
++
++ mov .LsetBit(%rip), $hlp
++ mov %rsp, $rsp_save
++ test \$15, $in_len
++ jz 1f
++ xor $hlp, $hlp
++ sub \$64, %rsp
++ vpxor $R0, $R0, $R0
++ vmovdqu $R0, (%rsp)
++ vmovdqu $R0, 32(%rsp)
++3:
++ movb ($in, $hlp), %r8b
++ movb %r8b, (%rsp, $hlp)
++ inc $hlp
++ cmp $hlp, $in_len
++ jne 3b
++
++ movb \$1, (%rsp, $hlp)
++ xor $hlp, $hlp
++ mov %rsp, $in
++
++1:
++
++ cmp \$16, $in_len
++ ja 2f
++ vmovq 8*0($in), $R0_x
++ vmovq 8*1($in), $R1_x
++ vmovq $hlp, $SET_MASK_x
++ vmovdqa .LpermFix(%rip), $PERM_MASK
++ jmp 1f
++2:
++ cmp \$32, $in_len
++ ja 2f
++ vmovdqu 16*0($in), $R2_x
++ vmovdqu 16*1($in), $R3_x
++ vmovq .LsetBit(%rip), $SET_MASK_x
++ vpinsrq \$1, $hlp, $SET_MASK_x, $SET_MASK_x
++ vmovdqa .LpermFix+32(%rip), $PERM_MASK
++
++ vpunpcklqdq $R3, $R2, $R0
++ vpunpckhqdq $R3, $R2, $R1
++ jmp 1f
++2:
++ cmp \$48, $in_len
++ ja 2f
++ vmovdqu 32*0($in), $R2
++ vmovdqu 32*1($in), $R3_x
++ vmovq .LsetBit(%rip), $SET_MASK_x
++ vpinsrq \$1, $hlp, $SET_MASK_x, $SET_MASK_x
++ vpermq \$0xc4, $SET_MASK, $SET_MASK
++ vmovdqa .LpermFix+64(%rip), $PERM_MASK
++
++ vpunpcklqdq $R3, $R2, $R0
++ vpunpckhqdq $R3, $R2, $R1
++ jmp 1f
++2:
++ vmovdqu 32*0($in), $R2
++ vmovdqu 32*1($in), $R3
++ vmovq .LsetBit(%rip), $SET_MASK_x
++ vpinsrq \$1, $hlp, $SET_MASK_x, $SET_MASK_x
++ vpermq \$0x40, $SET_MASK, $SET_MASK
++ vmovdqa .LpermFix+96(%rip), $PERM_MASK
++
++ vpunpcklqdq $R3, $R2, $R0
++ vpunpckhqdq $R3, $R2, $R1
++
++1:
++ mov $rsp_save, %rsp
++
++ vpsrlq \$26, $R0, $R2
++ vpand $AND_MASK, $R0, $R0
++ vpaddq $R0, $A0, $A0
++
++ vpsrlq \$26, $R2, $R0
++ vpand $AND_MASK, $R2, $R2
++ vpaddq $R2, $A1, $A1
++
++ vpsllq \$12, $R1, $R2
++ vpxor $R2, $R0, $R0
++ vpand $AND_MASK, $R0, $R0
++ vpaddq $R0, $A2, $A2
++
++ vpsrlq \$26, $R2, $R0
++ vpsrlq \$40, $R1, $R2
++ vpand $AND_MASK, $R0, $R0
++ vpxor $SET_MASK, $R2, $R2
++ vpaddq $R0, $A3, $A3
++ vpaddq $R2, $A4, $A4
++
++ # Multiply input by R[0]
++ vmovdqu $_r0_($state), $T0
++ vpermd $T0, $PERM_MASK, $T0
++ vpmuludq $T0, $A0, $R0
++ vpmuludq $T0, $A1, $R1
++ vpmuludq $T0, $A2, $R2
++ vpmuludq $T0, $A3, $R3
++ vpmuludq $T0, $A4, $R4
++ # Multiply input by R[1] (and R[1]*5)
++ vmovdqu $_r1_x5($state), $T0
++ vpermd $T0, $PERM_MASK, $T0
++ vpmuludq $T0, $A4, $T1
++ vpaddq $T1, $R0, $R0
++ vmovdqu $_r1_($state), $T0
++ vpermd $T0, $PERM_MASK, $T0
++ vpmuludq $T0, $A0, $T1
++ vpaddq $T1, $R1, $R1
++ vpmuludq $T0, $A1, $T1
++ vpaddq $T1, $R2, $R2
++ vpmuludq $T0, $A2, $T1
++ vpaddq $T1, $R3, $R3
++ vpmuludq $T0, $A3, $T1
++ vpaddq $T1, $R4, $R4
++ # Etc
++ vmovdqu $_r2_x5($state), $T0
++ vpermd $T0, $PERM_MASK, $T0
++ vpmuludq $T0, $A3, $T1
++ vpaddq $T1, $R0, $R0
++ vpmuludq $T0, $A4, $T1
++ vpaddq $T1, $R1, $R1
++ vmovdqu $_r2_($state), $T0
++ vpermd $T0, $PERM_MASK, $T0
++ vpmuludq $T0, $A0, $T1
++ vpaddq $T1, $R2, $R2
++ vpmuludq $T0, $A1, $T1
++ vpaddq $T1, $R3, $R3
++ vpmuludq $T0, $A2, $T1
++ vpaddq $T1, $R4, $R4
++
++ vmovdqu $_r3_x5($state), $T0
++ vpermd $T0, $PERM_MASK, $T0
++ vpmuludq $T0, $A2, $T1
++ vpaddq $T1, $R0, $R0
++ vpmuludq $T0, $A3, $T1
++ vpaddq $T1, $R1, $R1
++ vpmuludq $T0, $A4, $T1
++ vpaddq $T1, $R2, $R2
++ vmovdqu $_r3_($state), $T0
++ vpermd $T0, $PERM_MASK, $T0
++ vpmuludq $T0, $A0, $T1
++ vpaddq $T1, $R3, $R3
++ vpmuludq $T0, $A1, $T1
++ vpaddq $T1, $R4, $R4
++
++ vmovdqu $_r4_x5($state), $T0
++ vpermd $T0, $PERM_MASK, $T0
++ vpmuludq $T0, $A1, $T1
++ vpaddq $T1, $R0, $R0
++ vpmuludq $T0, $A2, $T1
++ vpaddq $T1, $R1, $R1
++ vpmuludq $T0, $A3, $T1
++ vpaddq $T1, $R2, $R2
++ vpmuludq $T0, $A4, $T1
++ vpaddq $T1, $R3, $R3
++ vmovdqu $_r4_($state), $T0
++ vpermd $T0, $PERM_MASK, $T0
++ vpmuludq $T0, $A0, $T1
++ vpaddq $T1, $R4, $R4
++ # Reduce
++ vpsrlq \$26, $R3, $T0
++ vpaddq $T0, $R4, $R4
++ vpand $AND_MASK, $R3, $R3
++ vpsrlq \$26, $R4, $T0
++ vpsllq \$2, $T0, $T1
++ vpaddq $T1, $T0, $T0
++ vpaddq $T0, $R0, $R0
++ vpand $AND_MASK, $R4, $R4
++ vpsrlq \$26, $R0, $T0
++ vpand $AND_MASK, $R0, $A0
++ vpaddq $T0, $R1, $R1
++ vpsrlq \$26, $R1, $T0
++ vpand $AND_MASK, $R1, $A1
++ vpaddq $T0, $R2, $R2
++ vpsrlq \$26, $R2, $T0
++ vpand $AND_MASK, $R2, $A2
++ vpaddq $T0, $R3, $R3
++ vpsrlq \$26, $R3, $T0
++ vpand $AND_MASK, $R3, $A3
++ vpaddq $T0, $R4, $A4
++
++ vpsrldq \$8, $A0, $R0
++ vpsrldq \$8, $A1, $R1
++ vpsrldq \$8, $A2, $R2
++ vpsrldq \$8, $A3, $R3
++ vpsrldq \$8, $A4, $R4
++
++ vpaddq $R0, $A0, $A0
++ vpaddq $R1, $A1, $A1
++ vpaddq $R2, $A2, $A2
++ vpaddq $R3, $A3, $A3
++ vpaddq $R4, $A4, $A4
++
++ vpermq \$0xAA, $A0, $R0
++ vpermq \$0xAA, $A1, $R1
++ vpermq \$0xAA, $A2, $R2
++ vpermq \$0xAA, $A3, $R3
++ vpermq \$0xAA, $A4, $R4
++
++ vpaddq $R0, $A0, $A0
++ vpaddq $R1, $A1, $A1
++ vpaddq $R2, $A2, $A2
++ vpaddq $R3, $A3, $A3
++ vpaddq $R4, $A4, $A4
++
++5:
++ vmovd $A0_x, $_A0_($state)
++ vmovd $A1_x, $_A1_($state)
++ vmovd $A2_x, $_A2_($state)
++ vmovd $A3_x, $_A3_($state)
++ vmovd $A4_x, $_A4_($state)
++
++ ret
++.size poly1305_update_avx2,.-poly1305_update_avx2
++###############################################################################
++# void poly1305_finish_avx2(void* $state, uint8_t mac[16]);
++.type poly1305_finish_avx2,\@function,2
++.globl poly1305_finish_avx2
++poly1305_finish_avx2:
++___
++my $mac="%rsi";
++my ($A0, $A1, $A2, $A3, $A4, $T0, $T1)=map("%xmm$_",(0..6));
++
++$code.=<<___;
++ vmovd $_A0_($state), $A0
++ vmovd $_A1_($state), $A1
++ vmovd $_A2_($state), $A2
++ vmovd $_A3_($state), $A3
++ vmovd $_A4_($state), $A4
++ # Reduce one last time in case there was a carry from 130 bit
++ vpsrlq \$26, $A4, $T0
++ vpsllq \$2, $T0, $T1
++ vpaddq $T1, $T0, $T0
++ vpaddq $T0, $A0, $A0
++ vpand .LandMask(%rip), $A4, $A4
++
++ vpsrlq \$26, $A0, $T0
++ vpand .LandMask(%rip), $A0, $A0
++ vpaddq $T0, $A1, $A1
++ vpsrlq \$26, $A1, $T0
++ vpand .LandMask(%rip), $A1, $A1
++ vpaddq $T0, $A2, $A2
++ vpsrlq \$26, $A2, $T0
++ vpand .LandMask(%rip), $A2, $A2
++ vpaddq $T0, $A3, $A3
++ vpsrlq \$26, $A3, $T0
++ vpand .LandMask(%rip), $A3, $A3
++ vpaddq $T0, $A4, $A4
++ # Convert to normal
++ vpsllq \$26, $A1, $T0
++ vpxor $T0, $A0, $A0
++ vpsllq \$52, $A2, $T0
++ vpxor $T0, $A0, $A0
++ vpsrlq \$12, $A2, $A1
++ vpsllq \$14, $A3, $T0
++ vpxor $T0, $A1, $A1
++ vpsllq \$40, $A4, $T0
++ vpxor $T0, $A1, $A1
++ vmovq $A0, %rax
++ vmovq $A1, %rdx
++
++ add $_k_($state), %rax
++ adc $_k_+8($state), %rdx
++ mov %rax, ($mac)
++ mov %rdx, 8($mac)
++
++ ret
++.size poly1305_finish_avx2,.-poly1305_finish_avx2
++___
++}
++}}
++
++$code =~ s/\`([^\`]*)\`/eval(\$1)/gem;
++print $code;
++close STDOUT;
+diff --git a/crypto/chacha20poly1305/chacha20.c b/crypto/chacha20poly1305/chacha20.c
+new file mode 100644
+index 0000000..72ab173
+--- /dev/null
++++ b/crypto/chacha20poly1305/chacha20.c
+@@ -0,0 +1,157 @@
++/* Copyright (c) 2014, Google Inc.
++ *
++ * Permission to use, copy, modify, and/or distribute this software for any
++ * purpose with or without fee is hereby granted, provided that the above
++ * copyright notice and this permission notice appear in all copies.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
++
++/* Adapted from the public domain, estream code by D. Bernstein. */
++
++#include <openssl/chacha20poly1305.h>
++
++/* sigma contains the ChaCha constants, which happen to be an ASCII string. */
++static const char sigma[16] = "expand 32-byte k";
++
++#define ROTATE(v, n) (((v) << (n)) | ((v) >> (32 - (n))))
++#define XOR(v, w) ((v) ^ (w))
++#define PLUS(x, y) ((x) + (y))
++#define PLUSONE(v) (PLUS((v), 1))
++
++#define U32TO8_LITTLE(p, v) \
++ { \
++ (p)[0] = (v >> 0) & 0xff; \
++ (p)[1] = (v >> 8) & 0xff; \
++ (p)[2] = (v >> 16) & 0xff; \
++ (p)[3] = (v >> 24) & 0xff; \
++ }
++
++#define U8TO32_LITTLE(p) \
++ (((uint32_t)((p)[0])) | ((uint32_t)((p)[1]) << 8) | \
++ ((uint32_t)((p)[2]) << 16) | ((uint32_t)((p)[3]) << 24))
++
++/* QUARTERROUND updates a, b, c, d with a ChaCha "quarter" round. */
++#define QUARTERROUND(a,b,c,d) \
++ x[a] = PLUS(x[a],x[b]); x[d] = ROTATE(XOR(x[d],x[a]),16); \
++ x[c] = PLUS(x[c],x[d]); x[b] = ROTATE(XOR(x[b],x[c]),12); \
++ x[a] = PLUS(x[a],x[b]); x[d] = ROTATE(XOR(x[d],x[a]), 8); \
++ x[c] = PLUS(x[c],x[d]); x[b] = ROTATE(XOR(x[b],x[c]), 7);
++
++/* chacha_core performs |num_rounds| rounds of ChaCha20 on the input words in
++ * |input| and writes the 64 output bytes to |output|. */
++static void chacha_core(uint8_t output[64], const uint32_t input[16]) {
++ uint32_t x[16];
++ int i;
++
++ memcpy(x, input, sizeof(uint32_t) * 16);
++ for (i = 20; i > 0; i -= 2) {
++ QUARTERROUND(0, 4, 8, 12)
++ QUARTERROUND(1, 5, 9, 13)
++ QUARTERROUND(2, 6, 10, 14)
++ QUARTERROUND(3, 7, 11, 15)
++ QUARTERROUND(0, 5, 10, 15)
++ QUARTERROUND(1, 6, 11, 12)
++ QUARTERROUND(2, 7, 8, 13)
++ QUARTERROUND(3, 4, 9, 14)
++ }
++
++ for (i = 0; i < 16; ++i) {
++ x[i] = PLUS(x[i], input[i]);
++ }
++ for (i = 0; i < 16; ++i) {
++ U32TO8_LITTLE(output + 4 * i, x[i]);
++ }
++}
++
++void CRYPTO_chacha_20(uint8_t *out, const uint8_t *in, size_t in_len,
++ const uint8_t key[32], const uint8_t nonce[8],
++ size_t counter) {
++#ifdef CHAPOLY_x86_64_ASM
++ uint8_t buf[256];
++ size_t buf_size, ctr_msk;
++ void (*core_func)(uint8_t *out, const uint8_t *in, size_t in_len,
++ const uint8_t key[32], const uint8_t nonce[8],
++ size_t counter) = NULL;
++#else
++ uint8_t buf[64];
++#endif
++ uint32_t input[16];
++ size_t todo, i;
++
++#ifdef CHAPOLY_x86_64_ASM
++
++ if ((OPENSSL_ia32cap_loc()[2] >> 5) & 1)
++ {
++ buf_size = 128;
++ core_func = chacha_20_core_avx2;
++ ctr_msk = -2;
++ }
++ else if ((OPENSSL_ia32cap_loc()[1] >> 28) & 1)
++ {
++ buf_size = 64;
++ core_func = chacha_20_core_avx;
++ ctr_msk = -1;
++ }
++ else goto do_legacy;
++
++ core_func(out, in, in_len, key, nonce, counter);
++ todo = in_len & (~(-buf_size));
++ if(todo)
++ {
++ out += in_len&(-buf_size);
++ in += in_len&(-buf_size);
++ counter += (in_len/64) & ctr_msk;
++ memcpy(buf, in, todo);
++ core_func(buf, buf, buf_size, key, nonce, counter);
++ memcpy(out, buf, todo);
++ memset(buf, 0, buf_size);
++ }
++ return;
++
++do_legacy:
++#endif
++
++ input[0] = U8TO32_LITTLE(sigma + 0);
++ input[1] = U8TO32_LITTLE(sigma + 4);
++ input[2] = U8TO32_LITTLE(sigma + 8);
++ input[3] = U8TO32_LITTLE(sigma + 12);
++
++ input[4] = U8TO32_LITTLE(key + 0);
++ input[5] = U8TO32_LITTLE(key + 4);
++ input[6] = U8TO32_LITTLE(key + 8);
++ input[7] = U8TO32_LITTLE(key + 12);
++
++ input[8] = U8TO32_LITTLE(key + 16);
++ input[9] = U8TO32_LITTLE(key + 20);
++ input[10] = U8TO32_LITTLE(key + 24);
++ input[11] = U8TO32_LITTLE(key + 28);
++
++ input[12] = counter;
++ input[13] = (uint64_t)counter >> 32;
++ input[14] = U8TO32_LITTLE(nonce + 0);
++ input[15] = U8TO32_LITTLE(nonce + 4);
++
++ while (in_len > 0) {
++ todo = 64;
++ if (in_len < todo) {
++ todo = in_len;
++ }
++
++ chacha_core(buf, input);
++ for (i = 0; i < todo; i++) {
++ out[i] = in[i] ^ buf[i];
++ }
++
++ out += todo;
++ in += todo;
++ in_len -= todo;
++
++ ((uint64_t*)input)[6]++;
++ }
++}
+diff --git a/crypto/chacha20poly1305/chacha20poly1305.h b/crypto/chacha20poly1305/chacha20poly1305.h
+new file mode 100644
+index 0000000..bcabbb4
+--- /dev/null
++++ b/crypto/chacha20poly1305/chacha20poly1305.h
+@@ -0,0 +1,63 @@
++#ifndef OPENSSL_HEADER_POLY1305_H
++#define OPENSSL_HEADER_POLY1305_H
++
++#include <stdint.h>
++#include <stddef.h>
++#include <string.h>
++#include "crypto.h"
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++#define POLY1305_MAC_LEN (16)
++
++typedef unsigned char poly1305_state[512];
++
++
++/* CRYPTO_poly1305_init sets up |state| so that it can be used to calculate an
++ * authentication tag with the one-time key |key|. Note that |key| is a
++ * one-time key and therefore there is no `reset' method because that would
++ * enable several messages to be authenticated with the same key. */
++void CRYPTO_poly1305_init(poly1305_state* state, const uint8_t key[32]);
++
++/* CRYPTO_poly1305_update processes |in_len| bytes from |in|. It can be called
++ * zero or more times after poly1305_init. */
++void CRYPTO_poly1305_update(poly1305_state* state, const uint8_t* in,
++ size_t in_len);
++
++/* CRYPTO_poly1305_finish completes the poly1305 calculation and writes a 16
++ * byte authentication tag to |mac|. */
++void CRYPTO_poly1305_finish(poly1305_state* state, uint8_t mac[16]);
++
++/* CRYPTO_chacha_20 encrypts |in_len| bytes from |in| with the given key and
++ * nonce and writes the result to |out|, which may be equal to |in|. The
++ * initial block counter is specified by |counter|. */
++void CRYPTO_chacha_20(uint8_t *out, const uint8_t *in, size_t in_len,
++ const uint8_t key[32], const uint8_t nonce[8],
++ size_t counter);
++
++#ifdef CHAPOLY_x86_64_ASM
++void poly1305_init_avx(poly1305_state* state, const uint8_t key[32]);
++void poly1305_update_avx(poly1305_state* state, const uint8_t *in, size_t in_len);
++void poly1305_finish_avx(poly1305_state* state, uint8_t mac[16]);
++
++void poly1305_init_avx2(poly1305_state* state, const uint8_t key[32]);
++void poly1305_update_avx2(poly1305_state* state, const uint8_t *in, size_t in_len);
++void poly1305_finish_avx2(poly1305_state* state, uint8_t mac[16]);
++
++void chacha_20_core_avx(uint8_t *out, const uint8_t *in, size_t in_len,
++ const uint8_t key[32], const uint8_t nonce[8],
++ size_t counter);
++
++void chacha_20_core_avx2(uint8_t *out, const uint8_t *in, size_t in_len,
++ const uint8_t key[32], const uint8_t nonce[8],
++ size_t counter);
++#endif
++
++
++#if defined(__cplusplus)
++} /* extern C */
++#endif
++
++#endif /* OPENSSL_HEADER_POLY1305_H */
+diff --git a/crypto/chacha20poly1305/chapolytest.c b/crypto/chacha20poly1305/chapolytest.c
+new file mode 100644
+index 0000000..56e713e
+--- /dev/null
++++ b/crypto/chacha20poly1305/chapolytest.c
+@@ -0,0 +1,287 @@
++/* ====================================================================
++ * Copyright (c) 2011-2013 The OpenSSL Project. All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ *
++ * 1. Redistributions of source code must retain the above copyright
++ * notice, this list of conditions and the following disclaimer.
++ *
++ * 2. Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in
++ * the documentation and/or other materials provided with the
++ * distribution.
++ *
++ * 3. All advertising materials mentioning features or use of this
++ * software must display the following acknowledgment:
++ * "This product includes software developed by the OpenSSL Project
++ * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
++ *
++ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
++ * endorse or promote products derived from this software without
++ * prior written permission. For written permission, please contact
++ * licensing@OpenSSL.org.
++ *
++ * 5. Products derived from this software may not be called "OpenSSL"
++ * nor may "OpenSSL" appear in their names without prior written
++ * permission of the OpenSSL Project.
++ *
++ * 6. Redistributions of any form whatsoever must retain the following
++ * acknowledgment:
++ * "This product includes software developed by the OpenSSL Project
++ * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
++ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
++ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
++ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
++ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
++ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
++ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
++ * OF THE POSSIBILITY OF SUCH DAMAGE.
++ * ====================================================================
++ */
++
++
++#include <stdio.h>
++#include <stdlib.h>
++#include <string.h>
++#include <stdint.h>
++
++#include <openssl/chacha20poly1305.h>
++
++struct chacha_test {
++ const char *keyhex;
++ const char *noncehex;
++ const char *outhex;
++};
++
++struct poly1305_test
++ {
++ const char *inputhex;
++ const char *keyhex;
++ const char *outhex;
++ };
++
++static const struct chacha_test chacha_tests[] = {
++ {
++ "0000000000000000000000000000000000000000000000000000000000000000",
++ "0000000000000000",
++ "76b8e0ada0f13d90405d6ae55386bd28bdd219b8a08ded1aa836efcc8b770dc7da41597c5157488d7724e03fb8d84a376a43b8f41518a11cc387b669b2ee6586",
++ },
++ {
++ "0000000000000000000000000000000000000000000000000000000000000001",
++ "0000000000000000",
++ "4540f05a9f1fb296d7736e7b208e3c96eb4fe1834688d2604f450952ed432d41bbe2a0b6ea7566d2a5d1e7e20d42af2c53d792b1c43fea817e9ad275ae546963",
++ },
++ {
++ "0000000000000000000000000000000000000000000000000000000000000000",
++ "0000000000000001",
++ "de9cba7bf3d69ef5e786dc63973f653a0b49e015adbff7134fcb7df137821031e85a050278a7084527214f73efc7fa5b5277062eb7a0433e445f41e31afab757",
++ },
++ {
++ "0000000000000000000000000000000000000000000000000000000000000000",
++ "0100000000000000",
++ "ef3fdfd6c61578fbf5cf35bd3dd33b8009631634d21e42ac33960bd138e50d32111e4caf237ee53ca8ad6426194a88545ddc497a0b466e7d6bbdb0041b2f586b",
++ },
++ {
++ "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f",
++ "0001020304050607",
++ "f798a189f195e66982105ffb640bb7757f579da31602fc93ec01ac56f85ac3c134a4547b733b46413042c9440049176905d3be59ea1c53f15916155c2be8241a38008b9a26bc35941e2444177c8ade6689de95264986d95889fb60e84629c9bd9a5acb1cc118be563eb9b3a4a472f82e09a7e778492b562ef7130e88dfe031c79db9d4f7c7a899151b9a475032b63fc385245fe054e3dd5a97a5f576fe064025d3ce042c566ab2c507b138db853e3d6959660996546cc9c4a6eafdc777c040d70eaf46f76dad3979e5c5360c3317166a1c894c94a371876a94df7628fe4eaaf2ccb27d5aaae0ad7ad0f9d4b6ad3b54098746d4524d38407a6deb",
++ },
++};
++
++static const struct poly1305_test poly1305_tests[] = {
++ {
++ "",
++ "c8afaac331ee372cd6082de134943b174710130e9f6fea8d72293850a667d86c",
++ "4710130e9f6fea8d72293850a667d86c",
++ },
++ {
++ "48656c6c6f20776f726c6421",
++ "746869732069732033322d62797465206b657920666f7220506f6c7931333035",
++ "a6f745008f81c916a20dcc74eef2b2f0",
++ },
++ {
++ "0000000000000000000000000000000000000000000000000000000000000000",
++ "746869732069732033322d62797465206b657920666f7220506f6c7931333035",
++ "49ec78090e481ec6c26b33b91ccc0307",
++ },
++};
++
++static unsigned char hex_digit(char h)
++ {
++ if (h >= '0' && h <= '9')
++ return h - '0';
++ else if (h >= 'a' && h <= 'f')
++ return h - 'a' + 10;
++ else if (h >= 'A' && h <= 'F')
++ return h - 'A' + 10;
++ else
++ abort();
++ }
++
++static void hex_decode(unsigned char *out, const char* hex)
++ {
++ size_t j = 0;
++
++ while (*hex != 0)
++ {
++ unsigned char v = hex_digit(*hex++);
++ v <<= 4;
++ v |= hex_digit(*hex++);
++ out[j++] = v;
++ }
++ }
++
++static void hexdump(unsigned char *a, size_t len)
++ {
++ size_t i;
++
++ for (i = 0; i < len; i++)
++ printf("%02x", a[i]);
++ }
++
++/* misalign returns a pointer that points 0 to 15 bytes into |in| such that the
++ * returned pointer has alignment 1 mod 16. */
++static void* misalign(void* in)
++ {
++ intptr_t x = (intptr_t) in;
++ x += (17 - (x % 16)) % 16;
++ return (void*) x;
++ }
++
++int main()
++ {
++ unsigned num_tests =
++ sizeof(chacha_tests) / sizeof(struct chacha_test);
++ unsigned i;
++ unsigned char key_bytes[32 + 16];
++ unsigned char nonce_bytes[8 + 16] = {0};
++
++
++ for (i = 0; i < num_tests; i++)
++ {
++ unsigned char *key = misalign(key_bytes);
++ unsigned char *nonce = misalign(nonce_bytes);
++
++ printf("ChaCha20 test #%d\n", i);
++ const struct chacha_test *test = &chacha_tests[i];
++ unsigned char *expected, *out_bytes, *zero_bytes, *out, *zeros;
++ size_t len = strlen(test->outhex);
++
++ if (strlen(test->keyhex) != 32*2 ||
++ strlen(test->noncehex) != 8*2 ||
++ (len & 1) == 1)
++ return 1;
++
++ len /= 2;
++
++ hex_decode(key, test->keyhex);
++ hex_decode(nonce, test->noncehex);
++
++ expected = malloc(len);
++ out_bytes = malloc(len+16);
++ zero_bytes = malloc(len+16);
++ /* Attempt to test unaligned inputs. */
++ out = misalign(out_bytes);
++ zeros = misalign(zero_bytes);
++ memset(zeros, 0, len);
++
++ hex_decode(expected, test->outhex);
++ CRYPTO_chacha_20(out, zeros, len, key, nonce, 0);
++
++ if (memcmp(out, expected, len) != 0)
++ {
++ printf("ChaCha20 test #%d failed.\n", i);
++ printf("got: ");
++ hexdump(out, len);
++ printf("\nexpected: ");
++ hexdump(expected, len);
++ printf("\n");
++ return 1;
++ }
++
++ /* The last test has a large output. We test whether the
++ * counter works as expected by skipping the first 64 bytes of
++ * it. */
++ if (i == num_tests - 1)
++ {
++ CRYPTO_chacha_20(out, zeros, len - 64, key, nonce, 1);
++ if (memcmp(out, expected + 64, len - 64) != 0)
++ {
++ printf("ChaCha20 skip test failed.\n");
++ return 1;
++ }
++ }
++
++ free(expected);
++ free(zero_bytes);
++ free(out_bytes);
++ }
++ num_tests =
++ sizeof(poly1305_tests) / sizeof(struct poly1305_test);
++ unsigned char key[32], out[16], expected[16];
++ poly1305_state poly1305;
++
++ for (i = 0; i < num_tests; i++)
++ {
++ printf("Poly1305 test #%d\n", i);
++ const struct poly1305_test *test = &poly1305_tests[i];
++ unsigned char *in;
++ size_t inlen = strlen(test->inputhex);
++
++ if (strlen(test->keyhex) != sizeof(key)*2 ||
++ strlen(test->outhex) != sizeof(out)*2 ||
++ (inlen & 1) == 1)
++ return 1;
++
++ inlen /= 2;
++
++ hex_decode(key, test->keyhex);
++ hex_decode(expected, test->outhex);
++
++ in = malloc(inlen);
++
++ hex_decode(in, test->inputhex);
++
++#ifdef CHAPOLY_x86_64_ASM
++ if((OPENSSL_ia32cap_loc()[1] >> 5) & 1) {
++ poly1305_init_avx2(&poly1305, key);
++ poly1305_update_avx2(&poly1305, in, inlen);
++ poly1305_finish_avx2(&poly1305, out);
++ }
++ else if ((OPENSSL_ia32cap_loc()[0] >> 60) & 1) {
++ poly1305_init_avx(&poly1305, key);
++ poly1305_update_avx(&poly1305, in, inlen);
++ poly1305_finish_avx(&poly1305, out);
++ }
++ else
++#endif
++ {
++ CRYPTO_poly1305_init(&poly1305, key);
++ CRYPTO_poly1305_update(&poly1305, in, inlen);
++ CRYPTO_poly1305_finish(&poly1305, out);
++ }
++ if (memcmp(out, expected, sizeof(expected)) != 0)
++ {
++ printf("Poly1305 test #%d failed.\n", i);
++ printf("got: ");
++ hexdump(out, sizeof(out));
++ printf("\nexpected: ");
++ hexdump(expected, sizeof(expected));
++ printf("\n");
++ return 1;
++ }
++
++ free(in);
++ }
++
++ printf("PASS\n");
++ return 0;
++ }
+diff --git a/crypto/chacha20poly1305/poly1305.c b/crypto/chacha20poly1305/poly1305.c
+new file mode 100644
+index 0000000..8b065cd
+--- /dev/null
++++ b/crypto/chacha20poly1305/poly1305.c
+@@ -0,0 +1,285 @@
++/* Copyright (c) 2014, Google Inc.
++ *
++ * Permission to use, copy, modify, and/or distribute this software for any
++ * purpose with or without fee is hereby granted, provided that the above
++ * copyright notice and this permission notice appear in all copies.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
++ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
++ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
++ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
++
++/* This implementation of poly1305 is by Andrew Moon
++ * (https://github.com/floodyberry/poly1305-donna) and released as public
++ * domain. */
++
++#include <openssl/chacha20poly1305.h>
++#include <string.h>
++
++#if !defined(B_ENDIAN)
++/* We can assume little-endian. */
++static uint32_t U8TO32_LE(const uint8_t *m) {
++ uint32_t r;
++ memcpy(&r, m, sizeof(r));
++ return r;
++}
++
++static void U32TO8_LE(uint8_t *m, uint32_t v) { memcpy(m, &v, sizeof(v)); }
++#else
++static uint32_t U8TO32_LE(const uint8_t *m) {
++ return (uint32_t)m[0] | (uint32_t)m[1] << 8 | (uint32_t)m[2] << 16 |
++ (uint32_t)m[3] << 24;
++}
++
++static void U32TO8_LE(uint8_t *m, uint32_t v) {
++ m[0] = v;
++ m[1] = v >> 8;
++ m[2] = v >> 16;
++ m[3] = v >> 24;
++}
++#endif
++
++static uint64_t mul32x32_64(uint32_t a, uint32_t b) { return (uint64_t)a * b; }
++
++struct poly1305_state_st {
++ uint32_t r0, r1, r2, r3, r4;
++ uint32_t s1, s2, s3, s4;
++ uint32_t h0, h1, h2, h3, h4;
++ uint8_t buf[16];
++ unsigned int buf_used;
++ uint8_t key[16];
++};
++
++/* poly1305_blocks updates |state| given some amount of input data. This
++ * function may only be called with a |len| that is not a multiple of 16 at the
++ * end of the data. Otherwise the input must be buffered into 16 byte blocks. */
++static void poly1305_update(struct poly1305_state_st *state, const uint8_t *in,
++ size_t len) {
++ uint32_t t0, t1, t2, t3;
++ uint64_t t[5];
++ uint32_t b;
++ uint64_t c;
++ size_t j;
++ uint8_t mp[16];
++
++ if (len < 16) {
++ goto poly1305_donna_atmost15bytes;
++ }
++
++poly1305_donna_16bytes:
++ t0 = U8TO32_LE(in);
++ t1 = U8TO32_LE(in + 4);
++ t2 = U8TO32_LE(in + 8);
++ t3 = U8TO32_LE(in + 12);
++
++ in += 16;
++ len -= 16;
++
++ state->h0 += t0 & 0x3ffffff;
++ state->h1 += ((((uint64_t)t1 << 32) | t0) >> 26) & 0x3ffffff;
++ state->h2 += ((((uint64_t)t2 << 32) | t1) >> 20) & 0x3ffffff;
++ state->h3 += ((((uint64_t)t3 << 32) | t2) >> 14) & 0x3ffffff;
++ state->h4 += (t3 >> 8) | (1 << 24);
++
++poly1305_donna_mul:
++ t[0] = mul32x32_64(state->h0, state->r0) + mul32x32_64(state->h1, state->s4) +
++ mul32x32_64(state->h2, state->s3) + mul32x32_64(state->h3, state->s2) +
++ mul32x32_64(state->h4, state->s1);
++ t[1] = mul32x32_64(state->h0, state->r1) + mul32x32_64(state->h1, state->r0) +
++ mul32x32_64(state->h2, state->s4) + mul32x32_64(state->h3, state->s3) +
++ mul32x32_64(state->h4, state->s2);
++ t[2] = mul32x32_64(state->h0, state->r2) + mul32x32_64(state->h1, state->r1) +
++ mul32x32_64(state->h2, state->r0) + mul32x32_64(state->h3, state->s4) +
++ mul32x32_64(state->h4, state->s3);
++ t[3] = mul32x32_64(state->h0, state->r3) + mul32x32_64(state->h1, state->r2) +
++ mul32x32_64(state->h2, state->r1) + mul32x32_64(state->h3, state->r0) +
++ mul32x32_64(state->h4, state->s4);
++ t[4] = mul32x32_64(state->h0, state->r4) + mul32x32_64(state->h1, state->r3) +
++ mul32x32_64(state->h2, state->r2) + mul32x32_64(state->h3, state->r1) +
++ mul32x32_64(state->h4, state->r0);
++
++ state->h0 = (uint32_t)t[0] & 0x3ffffff;
++ c = (t[0] >> 26);
++ t[1] += c;
++ state->h1 = (uint32_t)t[1] & 0x3ffffff;
++ b = (uint32_t)(t[1] >> 26);
++ t[2] += b;
++ state->h2 = (uint32_t)t[2] & 0x3ffffff;
++ b = (uint32_t)(t[2] >> 26);
++ t[3] += b;
++ state->h3 = (uint32_t)t[3] & 0x3ffffff;
++ b = (uint32_t)(t[3] >> 26);
++ t[4] += b;
++ state->h4 = (uint32_t)t[4] & 0x3ffffff;
++ b = (uint32_t)(t[4] >> 26);
++ state->h0 += b * 5;
++
++ if (len >= 16)
++ goto poly1305_donna_16bytes;
++
++/* final bytes */
++poly1305_donna_atmost15bytes:
++ if (!len)
++ return;
++
++ for (j = 0; j < len; j++)
++ mp[j] = in[j];
++ mp[j++] = 1;
++ for (; j < 16; j++)
++ mp[j] = 0;
++ len = 0;
++
++ t0 = U8TO32_LE(mp + 0);
++ t1 = U8TO32_LE(mp + 4);
++ t2 = U8TO32_LE(mp + 8);
++ t3 = U8TO32_LE(mp + 12);
++
++ state->h0 += t0 & 0x3ffffff;
++ state->h1 += ((((uint64_t)t1 << 32) | t0) >> 26) & 0x3ffffff;
++ state->h2 += ((((uint64_t)t2 << 32) | t1) >> 20) & 0x3ffffff;
++ state->h3 += ((((uint64_t)t3 << 32) | t2) >> 14) & 0x3ffffff;
++ state->h4 += (t3 >> 8);
++
++ goto poly1305_donna_mul;
++}
++
++void CRYPTO_poly1305_init(poly1305_state *statep, const uint8_t key[32]) {
++ struct poly1305_state_st *state = (struct poly1305_state_st *)statep;
++ uint32_t t0, t1, t2, t3;
++
++ t0 = U8TO32_LE(key + 0);
++ t1 = U8TO32_LE(key + 4);
++ t2 = U8TO32_LE(key + 8);
++ t3 = U8TO32_LE(key + 12);
++
++ /* precompute multipliers */
++ state->r0 = t0 & 0x3ffffff;
++ t0 >>= 26;
++ t0 |= t1 << 6;
++ state->r1 = t0 & 0x3ffff03;
++ t1 >>= 20;
++ t1 |= t2 << 12;
++ state->r2 = t1 & 0x3ffc0ff;
++ t2 >>= 14;
++ t2 |= t3 << 18;
++ state->r3 = t2 & 0x3f03fff;
++ t3 >>= 8;
++ state->r4 = t3 & 0x00fffff;
++
++ state->s1 = state->r1 * 5;
++ state->s2 = state->r2 * 5;
++ state->s3 = state->r3 * 5;
++ state->s4 = state->r4 * 5;
++
++ /* init state */
++ state->h0 = 0;
++ state->h1 = 0;
++ state->h2 = 0;
++ state->h3 = 0;
++ state->h4 = 0;
++
++ state->buf_used = 0;
++ memcpy(state->key, key + 16, sizeof(state->key));
++}
++
++void CRYPTO_poly1305_update(poly1305_state *statep, const uint8_t *in,
++ size_t in_len) {
++ unsigned int i;
++ struct poly1305_state_st *state = (struct poly1305_state_st *)statep;
++
++ if (state->buf_used) {
++ unsigned int todo = 16 - state->buf_used;
++ if (todo > in_len)
++ todo = in_len;
++ for (i = 0; i < todo; i++)
++ state->buf[state->buf_used + i] = in[i];
++ state->buf_used += todo;
++ in_len -= todo;
++ in += todo;
++
++ if (state->buf_used == 16) {
++ poly1305_update(state, state->buf, 16);
++ state->buf_used = 0;
++ }
++ }
++
++ if (in_len >= 16) {
++ size_t todo = in_len & ~0xf;
++ poly1305_update(state, in, todo);
++ in += todo;
++ in_len &= 0xf;
++ }
++
++ if (in_len) {
++ for (i = 0; i < in_len; i++)
++ state->buf[i] = in[i];
++ state->buf_used = in_len;
++ }
++}
++
++void CRYPTO_poly1305_finish(poly1305_state *statep, uint8_t mac[16]) {
++ struct poly1305_state_st *state = (struct poly1305_state_st *)statep;
++ uint64_t f0, f1, f2, f3;
++ uint32_t g0, g1, g2, g3, g4;
++ uint32_t b, nb;
++
++ if (state->buf_used)
++ poly1305_update(state, state->buf, state->buf_used);
++
++ b = state->h0 >> 26;
++ state->h0 = state->h0 & 0x3ffffff;
++ state->h1 += b;
++ b = state->h1 >> 26;
++ state->h1 = state->h1 & 0x3ffffff;
++ state->h2 += b;
++ b = state->h2 >> 26;
++ state->h2 = state->h2 & 0x3ffffff;
++ state->h3 += b;
++ b = state->h3 >> 26;
++ state->h3 = state->h3 & 0x3ffffff;
++ state->h4 += b;
++ b = state->h4 >> 26;
++ state->h4 = state->h4 & 0x3ffffff;
++ state->h0 += b * 5;
++
++ g0 = state->h0 + 5;
++ b = g0 >> 26;
++ g0 &= 0x3ffffff;
++ g1 = state->h1 + b;
++ b = g1 >> 26;
++ g1 &= 0x3ffffff;
++ g2 = state->h2 + b;
++ b = g2 >> 26;
++ g2 &= 0x3ffffff;
++ g3 = state->h3 + b;
++ b = g3 >> 26;
++ g3 &= 0x3ffffff;
++ g4 = state->h4 + b - (1 << 26);
++
++ b = (g4 >> 31) - 1;
++ nb = ~b;
++ state->h0 = (state->h0 & nb) | (g0 & b);
++ state->h1 = (state->h1 & nb) | (g1 & b);
++ state->h2 = (state->h2 & nb) | (g2 & b);
++ state->h3 = (state->h3 & nb) | (g3 & b);
++ state->h4 = (state->h4 & nb) | (g4 & b);
++
++ f0 = ((state->h0) | (state->h1 << 26)) + (uint64_t)U8TO32_LE(&state->key[0]);
++ f1 = ((state->h1 >> 6) | (state->h2 << 20)) +
++ (uint64_t)U8TO32_LE(&state->key[4]);
++ f2 = ((state->h2 >> 12) | (state->h3 << 14)) +
++ (uint64_t)U8TO32_LE(&state->key[8]);
++ f3 = ((state->h3 >> 18) | (state->h4 << 8)) +
++ (uint64_t)U8TO32_LE(&state->key[12]);
++
++ U32TO8_LE(&mac[0], f0);
++ f1 += (f0 >> 32);
++ U32TO8_LE(&mac[4], f1);
++ f2 += (f1 >> 32);
++ U32TO8_LE(&mac[8], f2);
++ f3 += (f2 >> 32);
++ U32TO8_LE(&mac[12], f3);
++}
+diff --git a/crypto/cryptlib.c b/crypto/cryptlib.c
+index ca0e3cc..244c17e 100644
+--- a/crypto/cryptlib.c
++++ b/crypto/cryptlib.c
+@@ -654,19 +654,9 @@ const char *CRYPTO_get_lock_name(int type)
+ defined(_M_AMD64) || defined(_M_X64)
+
+ extern unsigned int OPENSSL_ia32cap_P[4];
+-unsigned long *OPENSSL_ia32cap_loc(void)
++unsigned int *OPENSSL_ia32cap_loc(void)
+ {
+- if (sizeof(long) == 4)
+- /*
+- * If 32-bit application pulls address of OPENSSL_ia32cap_P[0]
+- * clear second element to maintain the illusion that vector
+- * is 32-bit.
+- */
+- OPENSSL_ia32cap_P[1] = 0;
+-
+- OPENSSL_ia32cap_P[2] = 0;
+-
+- return (unsigned long *)OPENSSL_ia32cap_P;
++ return OPENSSL_ia32cap_P;
+ }
+
+ # if defined(OPENSSL_CPUID_OBJ) && !defined(OPENSSL_NO_ASM) && !defined(I386_ONLY)
+diff --git a/crypto/crypto.h b/crypto/crypto.h
+index c450d7a..aeacb00 100644
+--- a/crypto/crypto.h
++++ b/crypto/crypto.h
+@@ -590,7 +590,7 @@ void CRYPTO_mem_leaks_cb(CRYPTO_MEM_LEAK_CB *cb);
+ void OpenSSLDie(const char *file, int line, const char *assertion);
+ # define OPENSSL_assert(e) (void)((e) ? 0 : (OpenSSLDie(__FILE__, __LINE__, #e),1))
+
+-unsigned long *OPENSSL_ia32cap_loc(void);
++unsigned int *OPENSSL_ia32cap_loc(void);
+ # define OPENSSL_ia32cap (*(OPENSSL_ia32cap_loc()))
+ int OPENSSL_isservice(void);
+
+diff --git a/crypto/evp/Makefile b/crypto/evp/Makefile
+index aaaad98..e30b588 100644
+--- a/crypto/evp/Makefile
++++ b/crypto/evp/Makefile
+@@ -29,7 +29,8 @@ LIBSRC= encode.c digest.c evp_enc.c evp_key.c evp_acnf.c evp_cnf.c \
+ c_all.c c_allc.c c_alld.c evp_lib.c bio_ok.c \
+ evp_pkey.c evp_pbe.c p5_crpt.c p5_crpt2.c \
+ e_old.c pmeth_lib.c pmeth_fn.c pmeth_gn.c m_sigver.c \
+- e_aes_cbc_hmac_sha1.c e_aes_cbc_hmac_sha256.c e_rc4_hmac_md5.c
++ e_aes_cbc_hmac_sha1.c e_aes_cbc_hmac_sha256.c e_rc4_hmac_md5.c \
++ e_chacha20poly1305.c
+
+ LIBOBJ= encode.o digest.o evp_enc.o evp_key.o evp_acnf.o evp_cnf.o \
+ e_des.o e_bf.o e_idea.o e_des3.o e_camellia.o\
+@@ -42,7 +43,8 @@ LIBOBJ= encode.o digest.o evp_enc.o evp_key.o evp_acnf.o evp_cnf.o \
+ c_all.o c_allc.o c_alld.o evp_lib.o bio_ok.o \
+ evp_pkey.o evp_pbe.o p5_crpt.o p5_crpt2.o \
+ e_old.o pmeth_lib.o pmeth_fn.o pmeth_gn.o m_sigver.o \
+- e_aes_cbc_hmac_sha1.o e_aes_cbc_hmac_sha256.o e_rc4_hmac_md5.o
++ e_aes_cbc_hmac_sha1.o e_aes_cbc_hmac_sha256.o e_rc4_hmac_md5.o \
++ e_chacha20poly1305.o
+
+ SRC= $(LIBSRC)
+
+@@ -263,6 +265,7 @@ e_cast.o: ../../include/openssl/objects.h ../../include/openssl/opensslconf.h
+ e_cast.o: ../../include/openssl/opensslv.h ../../include/openssl/ossl_typ.h
+ e_cast.o: ../../include/openssl/safestack.h ../../include/openssl/stack.h
+ e_cast.o: ../../include/openssl/symhacks.h ../cryptlib.h e_cast.c evp_locl.h
++e_chacha20poly1305.o: ../../include/openssl/chacha20poly1305.h e_chacha20poly1305.c
+ e_des.o: ../../e_os.h ../../include/openssl/asn1.h ../../include/openssl/bio.h
+ e_des.o: ../../include/openssl/buffer.h ../../include/openssl/crypto.h
+ e_des.o: ../../include/openssl/des.h ../../include/openssl/des_old.h
+diff --git a/crypto/evp/e_chacha20poly1305.c b/crypto/evp/e_chacha20poly1305.c
+new file mode 100644
+index 0000000..0cb2af7
+--- /dev/null
++++ b/crypto/evp/e_chacha20poly1305.c
+@@ -0,0 +1,323 @@
++/* ====================================================================
++ * Copyright (c) 2001-2014 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
++ * openssl-core@openssl.org.
++ *
++ * 5. Products derived from this software may not be called "OpenSSL"
++ * nor may "OpenSSL" appear in their names without prior written
++ * permission of the OpenSSL Project.
++ *
++ * 6. Redistributions of any form whatsoever must retain the following
++ * acknowledgment:
++ * "This product includes software developed by the OpenSSL Project
++ * for use in the OpenSSL Toolkit (http://www.openssl.org/)"
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
++ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
++ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
++ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
++ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
++ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
++ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
++ * OF THE POSSIBILITY OF SUCH DAMAGE.
++ * ====================================================================
++ *
++ */
++
++#include <openssl/opensslconf.h>
++#ifndef OPENSSL_NO_CHACHA_POLY
++#include <openssl/evp.h>
++#include <openssl/err.h>
++#include <openssl/chacha20poly1305.h>
++#include "evp_locl.h"
++#include <openssl/rand.h>
++
++typedef struct
++ {
++ uint8_t key[32];
++ /* uint8_t salt[4] */;
++ uint8_t nonce[8];
++ poly1305_state poly_state;
++ size_t aad_l;
++ size_t ct_l;
++ int valid;
++#ifdef CHAPOLY_x86_64_ASM
++ void (*poly1305_init_ptr)(poly1305_state *, const uint8_t *);
++ void (*poly1305_update_ptr)(poly1305_state *, const uint8_t *, size_t);
++ void (*poly1305_finish_ptr)(poly1305_state *, uint8_t *);
++ #define poly_init aead_ctx->poly1305_init_ptr
++ #define poly_update poly1305_update_wrapper
++ #define poly_finish poly1305_finish_wrapper
++ #define FILL_BUFFER ((size_t)128)
++ uint8_t poly_buffer[FILL_BUFFER];
++ uint8_t chacha_buffer[FILL_BUFFER];
++ uint8_t poly_buffer_used;
++ uint8_t chacha_used;
++#else
++ #define poly_init CRYPTO_poly1305_init
++ #define poly_update(c,i,l) CRYPTO_poly1305_update(&c->poly_state,i,l)
++ #define poly_finish(c,m) CRYPTO_poly1305_finish(&c->poly_state,m)
++#endif
++ } EVP_CHACHA20_POLY1305_CTX;
++
++#ifdef CHAPOLY_x86_64_ASM
++static void poly1305_update_wrapper(EVP_CHACHA20_POLY1305_CTX *ctx, const uint8_t *in, size_t in_len)
++ {
++ int todo;
++ /* Attempt to fill as many bytes as possible before calling the update function */
++ if(in_len < FILL_BUFFER || ctx->poly_buffer_used)
++ {
++ todo = FILL_BUFFER - ctx->poly_buffer_used;
++ todo = in_len < todo? in_len : todo;
++ memcpy(ctx->poly_buffer + ctx->poly_buffer_used, in, todo);
++ ctx->poly_buffer_used += todo;
++ in += todo;
++ in_len -= todo;
++ if(ctx->poly_buffer_used == FILL_BUFFER)
++ {
++ ctx->poly1305_update_ptr(&ctx->poly_state, ctx->poly_buffer, FILL_BUFFER);
++ ctx->poly_buffer_used = 0;
++ }
++ }
++ if(in_len >= FILL_BUFFER)
++ {
++ ctx->poly1305_update_ptr(&ctx->poly_state, in, in_len&(-FILL_BUFFER));
++ in += in_len&(-FILL_BUFFER);
++ in_len &= (FILL_BUFFER-1);
++ }
++ if(in_len)
++ {
++ memcpy(ctx->poly_buffer, in, in_len);
++ ctx->poly_buffer_used = in_len;
++ }
++ }
++
++static void poly1305_finish_wrapper(EVP_CHACHA20_POLY1305_CTX *ctx, uint8_t mac[16])
++ {
++ if(ctx->poly_buffer_used)
++ {
++ if(ctx->poly_buffer_used % 16)
++ {
++ memset(ctx->poly_buffer + ctx->poly_buffer_used, 0, 16 - (ctx->poly_buffer_used%16));
++ }
++ ctx->poly1305_update_ptr(&ctx->poly_state, ctx->poly_buffer, ctx->poly_buffer_used);
++ }
++ ctx->poly1305_finish_ptr(&ctx->poly_state, mac);
++ memset(ctx->poly_buffer, 0 ,FILL_BUFFER);
++ }
++#endif
++
++static int EVP_chacha20_poly1305_init(EVP_CIPHER_CTX *ctx, const unsigned char *key, const unsigned char *iv, int enc)
++ {
++ EVP_CHACHA20_POLY1305_CTX *aead_ctx = ctx->cipher_data;
++ /* simply copy the chacha key and iv*/
++ memcpy(aead_ctx->key, key, 32);
++ /* memcpy(aead_ctx->salt, iv, 4); */
++ aead_ctx->valid = 0;
++ return 1;
++ }
++
++static int EVP_chacha20_poly1305_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in, size_t inl)
++ {
++ EVP_CHACHA20_POLY1305_CTX *aead_ctx = ctx->cipher_data;
++ uint8_t poly_block[16];
++ uint64_t cl;
++ if(!aead_ctx->valid)
++ return 0;
++ if (inl < 16)
++ return -1;
++ /* Fix for MAC */
++ inl -= 16;
++ /* Encryption */
++ if(ctx->encrypt)
++ {
++#ifdef FILL_BUFFER
++ /* we can use the buffer we already accumulated during the parallel computation in init */
++ if(inl<=FILL_BUFFER-64)
++ {
++ int i;
++ for(i=0; i<inl; i++)
++ out[i] = in[i] ^ aead_ctx->chacha_buffer[i+64];
++ }
++ else
++#endif
++ CRYPTO_chacha_20(out, in, inl, aead_ctx->key, aead_ctx->nonce, 1);
++ poly_update(aead_ctx, out, inl);
++ aead_ctx->ct_l += inl;
++ cl = aead_ctx->ct_l;
++ poly_update(aead_ctx, (uint8_t*)&cl, sizeof(cl));
++ poly_finish(aead_ctx, &out[inl]);
++ aead_ctx->valid = 0;
++ return inl+16;
++ }
++ /* Decryption */
++ else
++ {
++ /* Fix to accommodate for the MAC */
++ poly_update(aead_ctx, in, inl);
++#ifdef FILL_BUFFER
++ /* we can use the buffer we already accumulated during the parallel computation in init */
++ if(inl<=FILL_BUFFER-64)
++ {
++ int i;
++ for(i=0; i<inl; i++)
++ out[i] = in[i] ^ aead_ctx->chacha_buffer[i+64];
++ }
++ else
++#endif
++ CRYPTO_chacha_20(out, in, inl, aead_ctx->key, aead_ctx->nonce, 1);
++ aead_ctx->ct_l += inl;
++ cl = aead_ctx->ct_l;
++ poly_update(aead_ctx, (uint8_t*)&cl, sizeof(cl));
++ poly_finish(aead_ctx, poly_block);
++
++ uint64_t cmp = ((uint64_t*)poly_block)[0] ^ ((uint64_t*)(in + inl))[0];
++ cmp |= ((uint64_t*)poly_block)[1] ^ ((uint64_t*)(in + inl))[1];
++
++ /*if (memcmp(poly_block, in + inl, POLY1305_MAC_LEN)) */
++ if (cmp)
++ {
++ OPENSSL_cleanse(out, inl);
++ aead_ctx->valid = 0;
++ return -1;
++ }
++ aead_ctx->valid = 0;
++ return inl;
++ }
++ return 0;
++ }
++
++static int EVP_chacha20_poly1305_cleanup(EVP_CIPHER_CTX *ctx)
++ {
++ return 1;
++ }
++
++static int EVP_chacha20_poly1305_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg, void *ptr)
++ {
++ EVP_CHACHA20_POLY1305_CTX *aead_ctx = ctx->cipher_data;
++#ifndef FILL_BUFFER
++ uint8_t poly1305_key[32];
++#endif
++ uint8_t aad[13 + 8];
++ uint64_t thirteen = 13;
++
++ switch(type)
++ {
++ case EVP_CTRL_AEAD_TLS1_AAD:
++ if(arg!=13)
++ return 0;
++ /* Initialize poly keys */
++#ifndef FILL_BUFFER
++ memset(poly1305_key, 0, sizeof(poly1305_key));
++#else
++ memset(aead_ctx->chacha_buffer, 0, FILL_BUFFER);
++#endif
++ /* Salt is the IV (not in draft) */
++ /* memcpy(aead_ctx->nonce, aead_ctx->salt, 4); */
++ /* Take sequence number from AAD */
++ /* memcpy(&aead_ctx->nonce[4], ptr, 8); */
++ memcpy(aead_ctx->nonce, ptr, 8);
++
++#ifdef CHAPOLY_x86_64_ASM
++ aead_ctx->poly_buffer_used = 0;
++ if((OPENSSL_ia32cap_loc()[2] >> 5) & 1) /* AVX2 */
++ {
++ aead_ctx->poly1305_init_ptr = poly1305_init_avx2;
++ aead_ctx->poly1305_update_ptr = poly1305_update_avx2;
++ aead_ctx->poly1305_finish_ptr = poly1305_finish_avx2;
++ }
++ else if ((OPENSSL_ia32cap_loc()[1] >> 28) & 1) /* AVX */
++ {
++ aead_ctx->poly1305_init_ptr = poly1305_init_avx;
++ aead_ctx->poly1305_update_ptr = poly1305_update_avx;
++ aead_ctx->poly1305_finish_ptr = poly1305_finish_avx;
++ }
++ else /*C*/
++ {
++ aead_ctx->poly1305_init_ptr = CRYPTO_poly1305_init;
++ aead_ctx->poly1305_update_ptr = CRYPTO_poly1305_update;
++ aead_ctx->poly1305_finish_ptr = CRYPTO_poly1305_finish;
++ }
++
++#endif
++#ifndef FILL_BUFFER
++ CRYPTO_chacha_20(poly1305_key, poly1305_key, sizeof(poly1305_key), aead_ctx->key, aead_ctx->nonce, 0);
++ poly_init(&aead_ctx->poly_state, poly1305_key);
++#else
++ CRYPTO_chacha_20(aead_ctx->chacha_buffer, aead_ctx->chacha_buffer, FILL_BUFFER, aead_ctx->key, aead_ctx->nonce, 0);
++ poly_init(&aead_ctx->poly_state, aead_ctx->chacha_buffer);
++ aead_ctx->chacha_used = 64; /* We keep 64 byte for future use, to accelerate for very short messages */
++#endif
++ aead_ctx->aad_l = 0;
++ aead_ctx->ct_l = 0;
++ /* Absorb AAD */
++ memcpy(aad, ptr, arg);
++ memcpy(&aad[arg], &thirteen, sizeof(thirteen));
++ /* If decrypting fix length for tag */
++ if (!ctx->encrypt)
++ {
++ unsigned int len=aad[arg-2]<<8|aad[arg-1];
++ len -= POLY1305_MAC_LEN;
++ aad[arg-2] = len>>8;
++ aad[arg-1] = len & 0xff;
++ }
++ poly_update(aead_ctx, aad, arg + sizeof(thirteen));
++ /* aead_ctx->aad_l += arg; */
++ aead_ctx->valid = 1;
++ return POLY1305_MAC_LEN;
++ break;
++ default:
++ return 0;
++ break;
++ }
++ return 0;
++ }
++
++#define CUSTOM_FLAGS (\
++ EVP_CIPH_CUSTOM_IV | EVP_CIPH_FLAG_CUSTOM_CIPHER \
++ | EVP_CIPH_ALWAYS_CALL_INIT \
++ | EVP_CIPH_CUSTOM_COPY)
++
++static const EVP_CIPHER chacha20_poly1305 = {
++ NID_chacha20_poly1305, /* nid */
++ 1, /* block size, sorta */
++ 32, /* key len */
++ 0, /* iv len */
++ CUSTOM_FLAGS|EVP_CIPH_FLAG_AEAD_CIPHER, /* flags */
++ EVP_chacha20_poly1305_init,
++ EVP_chacha20_poly1305_cipher,
++ EVP_chacha20_poly1305_cleanup,
++ sizeof(EVP_CHACHA20_POLY1305_CTX), /* ctx size */
++ NULL, NULL,
++ EVP_chacha20_poly1305_ctrl,
++ NULL
++ };
++
++const EVP_CIPHER *EVP_chacha20_poly1305(void)
++{ return &chacha20_poly1305; }
++
++#endif
+diff --git a/crypto/evp/evp.h b/crypto/evp/evp.h
+index 39ab793..5f2260a 100644
+--- a/crypto/evp/evp.h
++++ b/crypto/evp/evp.h
+@@ -893,6 +893,9 @@ const EVP_CIPHER *EVP_camellia_256_cfb128(void);
+ # define EVP_camellia_256_cfb EVP_camellia_256_cfb128
+ const EVP_CIPHER *EVP_camellia_256_ofb(void);
+ # endif
++# ifndef OPENSSL_NO_CHACHA_POLY
++const EVP_CIPHER *EVP_chacha20_poly1305(void);
++# endif
+
+ # ifndef OPENSSL_NO_SEED
+ const EVP_CIPHER *EVP_seed_ecb(void);
+diff --git a/crypto/objects/obj_dat.h b/crypto/objects/obj_dat.h
+index b7e3cf2..4059875 100644
+--- a/crypto/objects/obj_dat.h
++++ b/crypto/objects/obj_dat.h
+@@ -62,9 +62,9 @@
+ * [including the GNU Public Licence.]
+ */
+
+-#define NUM_NID 958
+-#define NUM_SN 951
+-#define NUM_LN 951
++#define NUM_NID 959
++#define NUM_SN 952
++#define NUM_LN 952
+ #define NUM_OBJ 890
+
+ static const unsigned char lvalues[6255]={
+@@ -2514,6 +2514,8 @@ static const ASN1_OBJECT nid_objs[NUM_NID]={
+ NID_jurisdictionStateOrProvinceName,11,&(lvalues[6232]),0},
+ {"jurisdictionC","jurisdictionCountryName",
+ NID_jurisdictionCountryName,11,&(lvalues[6243]),0},
++{"id-chacha20-poly1305","chacha20-poly1305",NID_chacha20_poly1305,0,
++ NULL,0},
+ };
+
+ static const unsigned int sn_objs[NUM_SN]={
+@@ -2954,6 +2956,7 @@ static const unsigned int sn_objs[NUM_SN]={
+ 362, /* "id-cct-PKIResponse" */
+ 360, /* "id-cct-crs" */
+ 81, /* "id-ce" */
++958, /* "id-chacha20-poly1305" */
+ 680, /* "id-characteristic-two-basis" */
+ 263, /* "id-cmc" */
+ 334, /* "id-cmc-addExtensions" */
+@@ -3728,6 +3731,7 @@ static const unsigned int ln_objs[NUM_LN]={
+ 677, /* "certicom-arc" */
+ 517, /* "certificate extensions" */
+ 883, /* "certificateRevocationList" */
++958, /* "chacha20-poly1305" */
+ 54, /* "challengePassword" */
+ 407, /* "characteristic-two-field" */
+ 395, /* "clearance" */
+diff --git a/crypto/objects/obj_mac.h b/crypto/objects/obj_mac.h
+index 779c309..2a34635 100644
+--- a/crypto/objects/obj_mac.h
++++ b/crypto/objects/obj_mac.h
+@@ -4192,3 +4192,7 @@
+ #define LN_jurisdictionCountryName "jurisdictionCountryName"
+ #define NID_jurisdictionCountryName 957
+ #define OBJ_jurisdictionCountryName 1L,3L,6L,1L,4L,1L,311L,60L,2L,1L,3L
++
++#define SN_chacha20_poly1305 "id-chacha20-poly1305"
++#define LN_chacha20_poly1305 "chacha20-poly1305"
++#define NID_chacha20_poly1305 958
+diff --git a/ssl/s3_lib.c b/ssl/s3_lib.c
+index ad9eeb6..a654176 100644
+--- a/ssl/s3_lib.c
++++ b/ssl/s3_lib.c
+@@ -2891,6 +2891,53 @@ OPENSSL_GLOBAL SSL_CIPHER ssl3_ciphers[] = {
+ 256},
+ #endif
+
++ /* Chacha20-Poly1305 draft cipher suites */
++#if !defined(OPENSSL_NO_CHACHA_POLY)
++ {
++ 1,
++ TLS1_TXT_ECDHE_RSA_WITH_CHACHA20_POLY1305,
++ TLS1_CK_ECDHE_RSA_CHACHA20_POLY1305,
++ SSL_kEECDH,
++ SSL_aRSA,
++ SSL_CHACHA20POLY1305,
++ SSL_AEAD,
++ SSL_TLSV1_2,
++ SSL_NOT_EXP|SSL_HIGH,
++ SSL_HANDSHAKE_MAC_SHA256|TLS1_PRF_SHA256,
++ 256,
++ 0,
++ },
++
++ {
++ 1,
++ TLS1_TXT_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,
++ TLS1_CK_ECDHE_ECDSA_CHACHA20_POLY1305,
++ SSL_kEECDH,
++ SSL_aECDSA,
++ SSL_CHACHA20POLY1305,
++ SSL_AEAD,
++ SSL_TLSV1_2,
++ SSL_NOT_EXP|SSL_HIGH,
++ SSL_HANDSHAKE_MAC_SHA256|TLS1_PRF_SHA256,
++ 256,
++ 0,
++ },
++
++ {
++ 1,
++ TLS1_TXT_DHE_RSA_WITH_CHACHA20_POLY1305,
++ TLS1_CK_DHE_RSA_CHACHA20_POLY1305,
++ SSL_kEDH,
++ SSL_aRSA,
++ SSL_CHACHA20POLY1305,
++ SSL_AEAD,
++ SSL_TLSV1_2,
++ SSL_NOT_EXP|SSL_HIGH,
++ SSL_HANDSHAKE_MAC_SHA256|TLS1_PRF_SHA256,
++ 256,
++ 0,
++ },
++#endif
+ /* end of list */
+ };
+
+@@ -4047,6 +4094,7 @@ SSL_CIPHER *ssl3_choose_cipher(SSL *s, STACK_OF(SSL_CIPHER) *clnt,
+ int i, ii, ok;
+ CERT *cert;
+ unsigned long alg_k, alg_a, mask_k, mask_a, emask_k, emask_a;
++ int use_chacha = 0;
+
+ /* Let's see which ciphers we can support */
+ cert = s->cert;
+@@ -4080,9 +4128,16 @@ SSL_CIPHER *ssl3_choose_cipher(SSL *s, STACK_OF(SSL_CIPHER) *clnt,
+ if (s->options & SSL_OP_CIPHER_SERVER_PREFERENCE || tls1_suiteb(s)) {
+ prio = srvr;
+ allow = clnt;
++ /* Use ChaCha20+Poly1305 iff it's client's most preferred cipher suite */
++ if (sk_SSL_CIPHER_num(clnt) > 0) {
++ c = sk_SSL_CIPHER_value(clnt, 0);
++ if (c->algorithm_enc == SSL_CHACHA20POLY1305)
++ use_chacha = 1;
++ }
+ } else {
+ prio = clnt;
+- allow = srvr;
++ allow = srvr;
++ use_chacha = 1;
+ }
+
+ tls1_set_cert_validity(s);
+@@ -4094,6 +4149,11 @@ SSL_CIPHER *ssl3_choose_cipher(SSL *s, STACK_OF(SSL_CIPHER) *clnt,
+ if ((c->algorithm_ssl & SSL_TLSV1_2) && !SSL_USE_TLS1_2_CIPHERS(s))
+ continue;
+
++ /* Skip ChaCha unless top client priority */
++ if ((c->algorithm_enc == SSL_CHACHA20POLY1305) &&
++ !use_chacha)
++ continue;
++
+ ssl_set_cert_masks(cert, c);
+ mask_k = cert->mask_k;
+ mask_a = cert->mask_a;
+diff --git a/ssl/ssl.h b/ssl/ssl.h
+index c6c5bce..6367a52 100644
+--- a/ssl/ssl.h
++++ b/ssl/ssl.h
+@@ -297,6 +297,7 @@ extern "C" {
+ # define SSL_TXT_CAMELLIA128 "CAMELLIA128"
+ # define SSL_TXT_CAMELLIA256 "CAMELLIA256"
+ # define SSL_TXT_CAMELLIA "CAMELLIA"
++# define SSL_TXT_CHACHA20 "CHACHA20"
+
+ # define SSL_TXT_MD5 "MD5"
+ # define SSL_TXT_SHA1 "SHA1"
+diff --git a/ssl/ssl_algs.c b/ssl/ssl_algs.c
+index e6f515f..4eff5ea 100644
+--- a/ssl/ssl_algs.c
++++ b/ssl/ssl_algs.c
+@@ -105,6 +105,10 @@ int SSL_library_init(void)
+ EVP_add_cipher(EVP_camellia_128_cbc());
+ EVP_add_cipher(EVP_camellia_256_cbc());
+ #endif
++
++#ifndef OPENSSL_NO_CHACHA_POLY
++ EVP_add_cipher(EVP_chacha20_poly1305());
++#endif
+
+ #ifndef OPENSSL_NO_SEED
+ EVP_add_cipher(EVP_seed_cbc());
+diff --git a/ssl/ssl_ciph.c b/ssl/ssl_ciph.c
+index a53f25b..e25db6d 100644
+--- a/ssl/ssl_ciph.c
++++ b/ssl/ssl_ciph.c
+@@ -164,7 +164,8 @@
+ #define SSL_ENC_SEED_IDX 11
+ #define SSL_ENC_AES128GCM_IDX 12
+ #define SSL_ENC_AES256GCM_IDX 13
+-#define SSL_ENC_NUM_IDX 14
++#define SSL_ENC_CHACHA20POLY1305_IDX 14
++#define SSL_ENC_NUM_IDX 15
+
+ static const EVP_CIPHER *ssl_cipher_methods[SSL_ENC_NUM_IDX] = {
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+@@ -316,6 +317,7 @@ static const SSL_CIPHER cipher_aliases[] = {
+ {0, SSL_TXT_CAMELLIA256, 0, 0, 0, SSL_CAMELLIA256, 0, 0, 0, 0, 0, 0},
+ {0, SSL_TXT_CAMELLIA, 0, 0, 0, SSL_CAMELLIA128 | SSL_CAMELLIA256, 0, 0, 0,
+ 0, 0, 0},
++ {0, SSL_TXT_CHACHA20, 0, 0, 0, SSL_CHACHA20POLY1305, 0, 0, 0, 0, 0, 0},
+
+ /* MAC aliases */
+ {0, SSL_TXT_MD5, 0, 0, 0, 0, SSL_MD5, 0, 0, 0, 0, 0},
+@@ -429,6 +431,9 @@ void ssl_load_ciphers(void)
+ ssl_cipher_methods[SSL_ENC_AES256GCM_IDX] =
+ EVP_get_cipherbyname(SN_aes_256_gcm);
+
++ ssl_cipher_methods[SSL_ENC_CHACHA20POLY1305_IDX] =
++ EVP_get_cipherbyname(SN_chacha20_poly1305);
++
+ ssl_digest_methods[SSL_MD_MD5_IDX] = EVP_get_digestbyname(SN_md5);
+ ssl_mac_secret_size[SSL_MD_MD5_IDX] =
+ EVP_MD_size(ssl_digest_methods[SSL_MD_MD5_IDX]);
+@@ -579,6 +584,9 @@ int ssl_cipher_get_evp(const SSL_SESSION *s, const EVP_CIPHER **enc,
+ case SSL_AES256GCM:
+ i = SSL_ENC_AES256GCM_IDX;
+ break;
++ case SSL_CHACHA20POLY1305:
++ i = SSL_ENC_CHACHA20POLY1305_IDX;
++ break;
+ default:
+ i = -1;
+ break;
+@@ -803,6 +811,8 @@ static void ssl_cipher_get_disabled(unsigned long *mkey, unsigned long *auth,
+ (ssl_cipher_methods[SSL_ENC_GOST89_IDX] ==
+ NULL) ? SSL_eGOST2814789CNT : 0;
+ *enc |= (ssl_cipher_methods[SSL_ENC_SEED_IDX] == NULL) ? SSL_SEED : 0;
++ *enc |= (ssl_cipher_methods[SSL_ENC_CHACHA20POLY1305_IDX] ==
++ NULL) ? SSL_CHACHA20POLY1305 : 0;
+
+ *mac |= (ssl_digest_methods[SSL_MD_MD5_IDX] == NULL) ? SSL_MD5 : 0;
+ *mac |= (ssl_digest_methods[SSL_MD_SHA1_IDX] == NULL) ? SSL_SHA1 : 0;
+@@ -1821,6 +1831,9 @@ char *SSL_CIPHER_description(const SSL_CIPHER *cipher, char *buf, int len)
+ case SSL_eGOST2814789CNT:
+ enc = "GOST89(256)";
+ break;
++ case SSL_CHACHA20POLY1305:
++ enc = "CHACHA20-POLY1305(256)";
++ break;
+ default:
+ enc = "unknown";
+ break;
+diff --git a/ssl/ssl_locl.h b/ssl/ssl_locl.h
+index 6c2c551..9e1cce3 100644
+--- a/ssl/ssl_locl.h
++++ b/ssl/ssl_locl.h
+@@ -354,6 +354,7 @@
+ # define SSL_SEED 0x00000800L
+ # define SSL_AES128GCM 0x00001000L
+ # define SSL_AES256GCM 0x00002000L
++# define SSL_CHACHA20POLY1305 0x00004000L
+
+ # define SSL_AES (SSL_AES128|SSL_AES256|SSL_AES128GCM|SSL_AES256GCM)
+ # define SSL_CAMELLIA (SSL_CAMELLIA128|SSL_CAMELLIA256)
+diff --git a/ssl/tls1.h b/ssl/tls1.h
+index 5929607..3a1ff70 100644
+--- a/ssl/tls1.h
++++ b/ssl/tls1.h
+@@ -566,6 +566,11 @@ SSL_CTX_callback_ctrl(ssl,SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB,(void (*)(void))cb)
+ # define TLS1_CK_ECDH_RSA_WITH_AES_128_GCM_SHA256 0x0300C031
+ # define TLS1_CK_ECDH_RSA_WITH_AES_256_GCM_SHA384 0x0300C032
+
++/* ChaCha20-Poly1305 ciphersuites draft-agl-tls-chacha20poly1305-01 */
++# define TLS1_CK_ECDHE_RSA_CHACHA20_POLY1305 0x0300CC13
++# define TLS1_CK_ECDHE_ECDSA_CHACHA20_POLY1305 0x0300CC14
++# define TLS1_CK_DHE_RSA_CHACHA20_POLY1305 0x0300CC15
++
+ /*
+ * XXX * Backward compatibility alert: + * Older versions of OpenSSL gave
+ * some DHE ciphers names with "EDH" + * instead of "DHE". Going forward, we
+@@ -716,6 +721,11 @@ SSL_CTX_callback_ctrl(ssl,SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB,(void (*)(void))cb)
+ # define TLS1_TXT_ECDH_RSA_WITH_AES_128_GCM_SHA256 "ECDH-RSA-AES128-GCM-SHA256"
+ # define TLS1_TXT_ECDH_RSA_WITH_AES_256_GCM_SHA384 "ECDH-RSA-AES256-GCM-SHA384"
+
++/* ChaCha20-Poly1305 ciphersuites draft-agl-tls-chacha20poly1305-01 */
++#define TLS1_TXT_ECDHE_RSA_WITH_CHACHA20_POLY1305 "ECDHE-RSA-CHACHA20-POLY1305"
++#define TLS1_TXT_ECDHE_ECDSA_WITH_CHACHA20_POLY1305 "ECDHE-ECDSA-CHACHA20-POLY1305"
++#define TLS1_TXT_DHE_RSA_WITH_CHACHA20_POLY1305 "DHE-RSA-CHACHA20-POLY1305"
++
+ # define TLS_CT_RSA_SIGN 1
+ # define TLS_CT_DSS_SIGN 2
+ # define TLS_CT_RSA_FIXED_DH 3
+diff --git a/test/Makefile b/test/Makefile
+index 80aeccf..bce42c5 100644
+--- a/test/Makefile
++++ b/test/Makefile
+@@ -70,6 +70,7 @@ HEARTBEATTEST= heartbeat_test
+ CONSTTIMETEST= constant_time_test
+ VERIFYEXTRATEST= verify_extra_test
+ CLIENTHELLOTEST= clienthellotest
++CHAPOLYTEST= chapolytest
+
+ TESTS= alltests
+
+@@ -83,7 +84,7 @@ EXE= $(BNTEST)$(EXE_EXT) $(ECTEST)$(EXE_EXT) $(ECDSATEST)$(EXE_EXT) $(ECDHTEST)
+ $(EVPTEST)$(EXE_EXT) $(EVPEXTRATEST)$(EXE_EXT) $(IGETEST)$(EXE_EXT) $(JPAKETEST)$(EXE_EXT) $(SRPTEST)$(EXE_EXT) \
+ $(ASN1TEST)$(EXE_EXT) $(V3NAMETEST)$(EXE_EXT) $(HEARTBEATTEST)$(EXE_EXT) \
+ $(CONSTTIMETEST)$(EXE_EXT) $(VERIFYEXTRATEST)$(EXE_EXT) \
+- $(CLIENTHELLOTEST)$(EXE_EXT)
++ $(CLIENTHELLOTEST)$(EXE_EXT) $(CHAPOLYTEST)$(EXE_EXT)
+
+ # $(METHTEST)$(EXE_EXT)
+
+@@ -97,7 +98,7 @@ OBJ= $(BNTEST).o $(ECTEST).o $(ECDSATEST).o $(ECDHTEST).o $(IDEATEST).o \
+ $(BFTEST).o $(SSLTEST).o $(DSATEST).o $(EXPTEST).o $(RSATEST).o \
+ $(EVPTEST).o $(EVPEXTRATEST).o $(IGETEST).o $(JPAKETEST).o $(ASN1TEST).o $(V3NAMETEST).o \
+ $(HEARTBEATTEST).o $(CONSTTIMETEST).o $(VERIFYEXTRATEST).o \
+- $(CLIENTHELLOTEST).o
++ $(CLIENTHELLOTEST).o $(CHAPOLYTEST).o
+
+ SRC= $(BNTEST).c $(ECTEST).c $(ECDSATEST).c $(ECDHTEST).c $(IDEATEST).c \
+ $(MD2TEST).c $(MD4TEST).c $(MD5TEST).c \
+@@ -108,7 +109,7 @@ SRC= $(BNTEST).c $(ECTEST).c $(ECDSATEST).c $(ECDHTEST).c $(IDEATEST).c \
+ $(BFTEST).c $(SSLTEST).c $(DSATEST).c $(EXPTEST).c $(RSATEST).c \
+ $(EVPTEST).c $(EVPEXTRATEST).c $(IGETEST).c $(JPAKETEST).c $(SRPTEST).c $(ASN1TEST).c \
+ $(V3NAMETEST).c $(HEARTBEATTEST).c $(CONSTTIMETEST).c $(VERIFYEXTRATEST).c \
+- $(CLIENTHELLOTEST).c
++ $(CLIENTHELLOTEST).c $(CHAPOLYTEST).c
+
+ EXHEADER=
+ HEADER= testutil.h $(EXHEADER)
+@@ -144,7 +145,7 @@ apps:
+ @(cd ..; $(MAKE) DIRS=apps all)
+
+ alltests: \
+- test_des test_idea test_sha test_md4 test_md5 test_hmac \
++ test_des test_idea test_sha test_md4 test_md5 test_hmac test_chapoly \
+ test_md2 test_mdc2 test_wp \
+ test_rmd test_rc2 test_rc4 test_rc5 test_bf test_cast test_aes \
+ test_rand test_bn test_ec test_ecdsa test_ecdh \
+@@ -361,6 +362,10 @@ test_clienthello: $(CLIENTHELLOTEST)$(EXE_EXT)
+ @echo $(START) $@
+ ../util/shlib_wrap.sh ./$(CLIENTHELLOTEST)
+
++test_chapoly: $(CHAPOLYTEST)$(EXE_EXT)
++ @echo "Test ChaCha20 and Poly1305"
++ ../util/shlib_wrap.sh ./$(CHAPOLYTEST)
++
+ lint:
+ lint -DLINT $(INCLUDES) $(SRC)>fluff
+
+@@ -538,6 +543,9 @@ $(VERIFYEXTRATEST)$(EXE_EXT): $(VERIFYEXTRATEST).o
+ $(CLIENTHELLOTEST)$(EXE_EXT): $(CLIENTHELLOTEST).o
+ @target=$(CLIENTHELLOTEST) $(BUILD_CMD)
+
++$(CHAPOLYTEST)$(EXE_EXT): $(CHAPOLYTEST).o
++ @target=$(CHAPOLYTEST); $(BUILD_CMD)
++
+ #$(AESTEST).o: $(AESTEST).c
+ # $(CC) -c $(CFLAGS) -DINTERMEDIATE_VALUE_KAT -DTRACE_KAT_MCT $(AESTEST).c
+
+@@ -605,6 +613,7 @@ clienthellotest.o: clienthellotest.c
+ constant_time_test.o: ../crypto/constant_time_locl.h ../e_os.h
+ constant_time_test.o: ../include/openssl/e_os2.h
+ constant_time_test.o: ../include/openssl/opensslconf.h constant_time_test.c
++chapolytest.o: ../include/openssl/chacha20poly1305.h chapolytest.c
+ destest.o: ../include/openssl/des.h ../include/openssl/des_old.h
+ destest.o: ../include/openssl/e_os2.h ../include/openssl/opensslconf.h
+ destest.o: ../include/openssl/ossl_typ.h ../include/openssl/safestack.h
+--
+1.9.1
+
diff --git a/dev-libs/openssl/files/openssl-1.0.2e-parallel-build.patch b/dev-libs/openssl/files/openssl-1.0.2e-parallel-build.patch
new file mode 100644
index 0000000..53d4baa
--- /dev/null
+++ b/dev-libs/openssl/files/openssl-1.0.2e-parallel-build.patch
@@ -0,0 +1,314 @@
+--- openssl-1.0.2e/crypto/Makefile
++++ openssl-1.0.2e/crypto/Makefile
+@@ -85,11 +85,11 @@
+ @if [ -z "$(THIS)" ]; then $(MAKE) -f $(TOP)/Makefile reflect THIS=$@; fi
+
+ subdirs:
+- @target=all; $(RECURSIVE_MAKE)
++ +@target=all; $(RECURSIVE_MAKE)
+
+ files:
+ $(PERL) $(TOP)/util/files.pl "CPUID_OBJ=$(CPUID_OBJ)" Makefile >> $(TOP)/MINFO
+- @target=files; $(RECURSIVE_MAKE)
++ +@target=files; $(RECURSIVE_MAKE)
+
+ links:
+ @$(PERL) $(TOP)/util/mklink.pl ../include/openssl $(EXHEADER)
+@@ -100,7 +100,7 @@
+ # lib: $(LIB): are splitted to avoid end-less loop
+ lib: $(LIB)
+ @touch lib
+-$(LIB): $(LIBOBJ)
++$(LIB): $(LIBOBJ) | subdirs
+ $(AR) $(LIB) $(LIBOBJ)
+ test -z "$(FIPSLIBDIR)" || $(AR) $(LIB) $(FIPSLIBDIR)fipscanister.o
+ $(RANLIB) $(LIB) || echo Never mind.
+@@ -111,7 +111,7 @@
+ fi
+
+ libs:
+- @target=lib; $(RECURSIVE_MAKE)
++ +@target=lib; $(RECURSIVE_MAKE)
+
+ install:
+ @[ -n "$(INSTALLTOP)" ] # should be set by top Makefile...
+@@ -120,7 +120,7 @@
+ (cp $$i $(INSTALL_PREFIX)$(INSTALLTOP)/include/openssl/$$i; \
+ chmod 644 $(INSTALL_PREFIX)$(INSTALLTOP)/include/openssl/$$i ); \
+ done;
+- @target=install; $(RECURSIVE_MAKE)
++ +@target=install; $(RECURSIVE_MAKE)
+
+ lint:
+ @target=lint; $(RECURSIVE_MAKE)
+--- openssl-1.0.2e/engines/Makefile
++++ openssl-1.0.2e/engines/Makefile
+@@ -72,7 +72,7 @@
+
+ all: lib subdirs
+
+-lib: $(LIBOBJ)
++lib: $(LIBOBJ) | subdirs
+ @if [ -n "$(SHARED_LIBS)" ]; then \
+ set -e; \
+ for l in $(LIBNAMES); do \
+@@ -89,7 +89,7 @@
+
+ subdirs:
+ echo $(EDIRS)
+- @target=all; $(RECURSIVE_MAKE)
++ +@target=all; $(RECURSIVE_MAKE)
+
+ files:
+ $(PERL) $(TOP)/util/files.pl Makefile >> $(TOP)/MINFO
+@@ -128,7 +128,7 @@
+ mv -f $(INSTALL_PREFIX)$(INSTALLTOP)/$(LIBDIR)/engines/$$pfx$$l$$sfx.new $(INSTALL_PREFIX)$(INSTALLTOP)/$(LIBDIR)/engines/$$pfx$$l$$sfx ); \
+ done; \
+ fi
+- @target=install; $(RECURSIVE_MAKE)
++ +@target=install; $(RECURSIVE_MAKE)
+
+ tags:
+ ctags $(SRC)
+--- openssl-1.0.2e/Makefile.org
++++ openssl-1.0.2e/Makefile.org
+@@ -280,17 +280,17 @@
+ build_libssl: build_ssl libssl.pc
+
+ build_crypto:
+- @dir=crypto; target=all; $(BUILD_ONE_CMD)
++ +@dir=crypto; target=all; $(BUILD_ONE_CMD)
+ build_ssl: build_crypto
+- @dir=ssl; target=all; $(BUILD_ONE_CMD)
++ +@dir=ssl; target=all; $(BUILD_ONE_CMD)
+ build_engines: build_crypto
+- @dir=engines; target=all; $(BUILD_ONE_CMD)
++ +@dir=engines; target=all; $(BUILD_ONE_CMD)
+ build_apps: build_libs
+- @dir=apps; target=all; $(BUILD_ONE_CMD)
++ +@dir=apps; target=all; $(BUILD_ONE_CMD)
+ build_tests: build_libs
+- @dir=test; target=all; $(BUILD_ONE_CMD)
++ +@dir=test; target=all; $(BUILD_ONE_CMD)
+ build_tools: build_libs
+- @dir=tools; target=all; $(BUILD_ONE_CMD)
++ +@dir=tools; target=all; $(BUILD_ONE_CMD)
+
+ all_testapps: build_libs build_testapps
+ build_testapps:
+@@ -548,7 +548,7 @@
+ (cp $$i $(INSTALL_PREFIX)$(INSTALLTOP)/include/openssl/$$i; \
+ chmod 644 $(INSTALL_PREFIX)$(INSTALLTOP)/include/openssl/$$i ); \
+ done;
+- @set -e; target=install; $(RECURSIVE_BUILD_CMD)
++ +@set -e; target=install; $(RECURSIVE_BUILD_CMD)
+ @set -e; liblist="$(LIBS)"; for i in $$liblist ;\
+ do \
+ if [ -f "$$i" ]; then \
+--- openssl-1.0.2e/Makefile.shared
++++ openssl-1.0.2e/Makefile.shared
+@@ -105,6 +105,7 @@
+ SHAREDFLAGS="$${SHAREDFLAGS:-$(CFLAGS) $(SHARED_LDFLAGS)}"; \
+ LIBPATH=`for x in $$LIBDEPS; do echo $$x; done | sed -e 's/^ *-L//;t' -e d | uniq`; \
+ LIBPATH=`echo $$LIBPATH | sed -e 's/ /:/g'`; \
++ [ -e $$SHLIB$$SHLIB_SOVER$$SHLIB_SUFFIX ] && exit 0; \
+ LD_LIBRARY_PATH=$$LIBPATH:$$LD_LIBRARY_PATH \
+ $${SHAREDCMD} $${SHAREDFLAGS} \
+ -o $$SHLIB$$SHLIB_SOVER$$SHLIB_SUFFIX \
+@@ -122,6 +123,7 @@
+ done; \
+ fi; \
+ if [ -n "$$SHLIB_SOVER" ]; then \
++ [ -e "$$SHLIB$$SHLIB_SUFFIX" ] || \
+ ( $(SET_X); rm -f $$SHLIB$$SHLIB_SUFFIX; \
+ ln -s $$prev $$SHLIB$$SHLIB_SUFFIX ); \
+ fi; \
+--- openssl-1.0.2e/test/Makefile
++++ openssl-1.0.2e/test/Makefile
+@@ -138,7 +138,7 @@
+ tags:
+ ctags $(SRC)
+
+-tests: exe apps $(TESTS)
++tests: exe $(TESTS)
+
+ apps:
+ @(cd ..; $(MAKE) DIRS=apps all)
+@@ -416,127 +416,127 @@
+ link_app.$${shlib_target}
+
+ $(RSATEST)$(EXE_EXT): $(RSATEST).o $(DLIBCRYPTO)
+- @target=$(RSATEST); $(BUILD_CMD)
++ +@target=$(RSATEST); $(BUILD_CMD)
+
+ $(BNTEST)$(EXE_EXT): $(BNTEST).o $(DLIBCRYPTO)
+- @target=$(BNTEST); $(BUILD_CMD)
++ +@target=$(BNTEST); $(BUILD_CMD)
+
+ $(ECTEST)$(EXE_EXT): $(ECTEST).o $(DLIBCRYPTO)
+- @target=$(ECTEST); $(BUILD_CMD)
++ +@target=$(ECTEST); $(BUILD_CMD)
+
+ $(EXPTEST)$(EXE_EXT): $(EXPTEST).o $(DLIBCRYPTO)
+- @target=$(EXPTEST); $(BUILD_CMD)
++ +@target=$(EXPTEST); $(BUILD_CMD)
+
+ $(IDEATEST)$(EXE_EXT): $(IDEATEST).o $(DLIBCRYPTO)
+- @target=$(IDEATEST); $(BUILD_CMD)
++ +@target=$(IDEATEST); $(BUILD_CMD)
+
+ $(MD2TEST)$(EXE_EXT): $(MD2TEST).o $(DLIBCRYPTO)
+- @target=$(MD2TEST); $(BUILD_CMD)
++ +@target=$(MD2TEST); $(BUILD_CMD)
+
+ $(SHATEST)$(EXE_EXT): $(SHATEST).o $(DLIBCRYPTO)
+- @target=$(SHATEST); $(BUILD_CMD)
++ +@target=$(SHATEST); $(BUILD_CMD)
+
+ $(SHA1TEST)$(EXE_EXT): $(SHA1TEST).o $(DLIBCRYPTO)
+- @target=$(SHA1TEST); $(BUILD_CMD)
++ +@target=$(SHA1TEST); $(BUILD_CMD)
+
+ $(SHA256TEST)$(EXE_EXT): $(SHA256TEST).o $(DLIBCRYPTO)
+- @target=$(SHA256TEST); $(BUILD_CMD)
++ +@target=$(SHA256TEST); $(BUILD_CMD)
+
+ $(SHA512TEST)$(EXE_EXT): $(SHA512TEST).o $(DLIBCRYPTO)
+- @target=$(SHA512TEST); $(BUILD_CMD)
++ +@target=$(SHA512TEST); $(BUILD_CMD)
+
+ $(RMDTEST)$(EXE_EXT): $(RMDTEST).o $(DLIBCRYPTO)
+- @target=$(RMDTEST); $(BUILD_CMD)
++ +@target=$(RMDTEST); $(BUILD_CMD)
+
+ $(MDC2TEST)$(EXE_EXT): $(MDC2TEST).o $(DLIBCRYPTO)
+- @target=$(MDC2TEST); $(BUILD_CMD)
++ +@target=$(MDC2TEST); $(BUILD_CMD)
+
+ $(MD4TEST)$(EXE_EXT): $(MD4TEST).o $(DLIBCRYPTO)
+- @target=$(MD4TEST); $(BUILD_CMD)
++ +@target=$(MD4TEST); $(BUILD_CMD)
+
+ $(MD5TEST)$(EXE_EXT): $(MD5TEST).o $(DLIBCRYPTO)
+- @target=$(MD5TEST); $(BUILD_CMD)
++ +@target=$(MD5TEST); $(BUILD_CMD)
+
+ $(HMACTEST)$(EXE_EXT): $(HMACTEST).o $(DLIBCRYPTO)
+- @target=$(HMACTEST); $(BUILD_CMD)
++ +@target=$(HMACTEST); $(BUILD_CMD)
+
+ $(WPTEST)$(EXE_EXT): $(WPTEST).o $(DLIBCRYPTO)
+- @target=$(WPTEST); $(BUILD_CMD)
++ +@target=$(WPTEST); $(BUILD_CMD)
+
+ $(RC2TEST)$(EXE_EXT): $(RC2TEST).o $(DLIBCRYPTO)
+- @target=$(RC2TEST); $(BUILD_CMD)
++ +@target=$(RC2TEST); $(BUILD_CMD)
+
+ $(BFTEST)$(EXE_EXT): $(BFTEST).o $(DLIBCRYPTO)
+- @target=$(BFTEST); $(BUILD_CMD)
++ +@target=$(BFTEST); $(BUILD_CMD)
+
+ $(CASTTEST)$(EXE_EXT): $(CASTTEST).o $(DLIBCRYPTO)
+- @target=$(CASTTEST); $(BUILD_CMD)
++ +@target=$(CASTTEST); $(BUILD_CMD)
+
+ $(RC4TEST)$(EXE_EXT): $(RC4TEST).o $(DLIBCRYPTO)
+- @target=$(RC4TEST); $(BUILD_CMD)
++ +@target=$(RC4TEST); $(BUILD_CMD)
+
+ $(RC5TEST)$(EXE_EXT): $(RC5TEST).o $(DLIBCRYPTO)
+- @target=$(RC5TEST); $(BUILD_CMD)
++ +@target=$(RC5TEST); $(BUILD_CMD)
+
+ $(DESTEST)$(EXE_EXT): $(DESTEST).o $(DLIBCRYPTO)
+- @target=$(DESTEST); $(BUILD_CMD)
++ +@target=$(DESTEST); $(BUILD_CMD)
+
+ $(RANDTEST)$(EXE_EXT): $(RANDTEST).o $(DLIBCRYPTO)
+- @target=$(RANDTEST); $(BUILD_CMD)
++ +@target=$(RANDTEST); $(BUILD_CMD)
+
+ $(DHTEST)$(EXE_EXT): $(DHTEST).o $(DLIBCRYPTO)
+- @target=$(DHTEST); $(BUILD_CMD)
++ +@target=$(DHTEST); $(BUILD_CMD)
+
+ $(DSATEST)$(EXE_EXT): $(DSATEST).o $(DLIBCRYPTO)
+- @target=$(DSATEST); $(BUILD_CMD)
++ +@target=$(DSATEST); $(BUILD_CMD)
+
+ $(METHTEST)$(EXE_EXT): $(METHTEST).o $(DLIBCRYPTO)
+- @target=$(METHTEST); $(BUILD_CMD)
++ +@target=$(METHTEST); $(BUILD_CMD)
+
+ $(SSLTEST)$(EXE_EXT): $(SSLTEST).o $(DLIBSSL) $(DLIBCRYPTO)
+- @target=$(SSLTEST); $(FIPS_BUILD_CMD)
++ +@target=$(SSLTEST); $(FIPS_BUILD_CMD)
+
+ $(ENGINETEST)$(EXE_EXT): $(ENGINETEST).o $(DLIBCRYPTO)
+- @target=$(ENGINETEST); $(BUILD_CMD)
++ +@target=$(ENGINETEST); $(BUILD_CMD)
+
+ $(EVPTEST)$(EXE_EXT): $(EVPTEST).o $(DLIBCRYPTO)
+- @target=$(EVPTEST); $(BUILD_CMD)
++ +@target=$(EVPTEST); $(BUILD_CMD)
+
+ $(EVPEXTRATEST)$(EXE_EXT): $(EVPEXTRATEST).o $(DLIBCRYPTO)
+- @target=$(EVPEXTRATEST); $(BUILD_CMD)
++ +@target=$(EVPEXTRATEST); $(BUILD_CMD)
+
+ $(ECDSATEST)$(EXE_EXT): $(ECDSATEST).o $(DLIBCRYPTO)
+- @target=$(ECDSATEST); $(BUILD_CMD)
++ +@target=$(ECDSATEST); $(BUILD_CMD)
+
+ $(ECDHTEST)$(EXE_EXT): $(ECDHTEST).o $(DLIBCRYPTO)
+- @target=$(ECDHTEST); $(BUILD_CMD)
++ +@target=$(ECDHTEST); $(BUILD_CMD)
+
+ $(IGETEST)$(EXE_EXT): $(IGETEST).o $(DLIBCRYPTO)
+- @target=$(IGETEST); $(BUILD_CMD)
++ +@target=$(IGETEST); $(BUILD_CMD)
+
+ $(JPAKETEST)$(EXE_EXT): $(JPAKETEST).o $(DLIBCRYPTO)
+- @target=$(JPAKETEST); $(BUILD_CMD)
++ +@target=$(JPAKETEST); $(BUILD_CMD)
+
+ $(ASN1TEST)$(EXE_EXT): $(ASN1TEST).o $(DLIBCRYPTO)
+- @target=$(ASN1TEST); $(BUILD_CMD)
++ +@target=$(ASN1TEST); $(BUILD_CMD)
+
+ $(SRPTEST)$(EXE_EXT): $(SRPTEST).o $(DLIBCRYPTO)
+- @target=$(SRPTEST); $(BUILD_CMD)
++ +@target=$(SRPTEST); $(BUILD_CMD)
+
+ $(V3NAMETEST)$(EXE_EXT): $(V3NAMETEST).o $(DLIBCRYPTO)
+- @target=$(V3NAMETEST); $(BUILD_CMD)
++ +@target=$(V3NAMETEST); $(BUILD_CMD)
+
+ $(HEARTBEATTEST)$(EXE_EXT): $(HEARTBEATTEST).o $(DLIBCRYPTO)
+- @target=$(HEARTBEATTEST); $(BUILD_CMD_STATIC)
++ +@target=$(HEARTBEATTEST); $(BUILD_CMD_STATIC)
+
+ $(CONSTTIMETEST)$(EXE_EXT): $(CONSTTIMETEST).o
+- @target=$(CONSTTIMETEST) $(BUILD_CMD)
++ +@target=$(CONSTTIMETEST) $(BUILD_CMD)
+
+ $(VERIFYEXTRATEST)$(EXE_EXT): $(VERIFYEXTRATEST).o
+- @target=$(VERIFYEXTRATEST) $(BUILD_CMD)
++ +@target=$(VERIFYEXTRATEST) $(BUILD_CMD)
+
+ $(CLIENTHELLOTEST)$(EXE_EXT): $(CLIENTHELLOTEST).o
+- @target=$(CLIENTHELLOTEST) $(BUILD_CMD)
++ +@target=$(CLIENTHELLOTEST) $(BUILD_CMD)
+
+ #$(AESTEST).o: $(AESTEST).c
+ # $(CC) -c $(CFLAGS) -DINTERMEDIATE_VALUE_KAT -DTRACE_KAT_MCT $(AESTEST).c
+@@ -549,7 +549,7 @@
+ # fi
+
+ dummytest$(EXE_EXT): dummytest.o $(DLIBCRYPTO)
+- @target=dummytest; $(BUILD_CMD)
++ +@target=dummytest; $(BUILD_CMD)
+
+ # DO NOT DELETE THIS LINE -- make depend depends on it.
+
diff --git a/dev-libs/openssl/metadata.xml b/dev-libs/openssl/metadata.xml
new file mode 100644
index 0000000..ddf3549
--- /dev/null
+++ b/dev-libs/openssl/metadata.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE pkgmetadata SYSTEM "http://www.gentoo.org/dtd/metadata.dtd">
+<pkgmetadata>
+ <herd></herd>
+ <maintainer>
+ <email>pigfoot@gmail.com</email>
+ <name>Chen, Chih-Chia</name>
+ <description>Maintainer. Assign bugs to him</description>
+ </maintainer>
+</pkgmetadata>
diff --git a/dev-libs/openssl/openssl-1.0.2e.ebuild b/dev-libs/openssl/openssl-1.0.2e.ebuild
new file mode 100644
index 0000000..ea214ab
--- /dev/null
+++ b/dev-libs/openssl/openssl-1.0.2e.ebuild
@@ -0,0 +1,269 @@
+# Copyright 1999-2015 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Id$
+
+EAPI="4"
+
+inherit eutils flag-o-matic toolchain-funcs multilib multilib-minimal
+
+MY_P=${P/_/-}
+DESCRIPTION="full-strength general purpose cryptography library (including SSL and TLS)"
+HOMEPAGE="http://www.openssl.org/"
+SRC_URI="mirror://openssl/source/${MY_P}.tar.gz"
+
+LICENSE="openssl"
+SLOT="0"
+KEYWORDS="alpha amd64 arm arm64 hppa ia64 m68k ~mips ppc ppc64 s390 sh sparc x86 ~amd64-fbsd ~sparc-fbsd ~x86-fbsd ~arm-linux ~x86-linux"
+IUSE="+asm bindist +cloudflare gmp kerberos rfc3779 sctp cpu_flags_x86_sse2 static-libs test +tls-heartbeat vanilla zlib"
+RESTRICT="!bindist? ( bindist )"
+
+# The blocks are temporary just to make sure people upgrade to a
+# version that lack runtime version checking. We'll drop them in
+# the future.
+RDEPEND=">=app-misc/c_rehash-1.7-r1
+ gmp? ( >=dev-libs/gmp-5.1.3-r1[static-libs(+)?,${MULTILIB_USEDEP}] )
+ zlib? ( >=sys-libs/zlib-1.2.8-r1[static-libs(+)?,${MULTILIB_USEDEP}] )
+ kerberos? ( >=app-crypt/mit-krb5-1.11.4[${MULTILIB_USEDEP}] )
+ abi_x86_32? (
+ !<=app-emulation/emul-linux-x86-baselibs-20140508
+ !app-emulation/emul-linux-x86-baselibs[-abi_x86_32(-)]
+ )
+ !<net-misc/openssh-5.9_p1-r4
+ !<net-libs/neon-0.29.6-r1"
+DEPEND="${RDEPEND}
+ >=dev-lang/perl-5
+ sctp? ( >=net-misc/lksctp-tools-1.0.12 )
+ test? (
+ sys-apps/diffutils
+ sys-devel/bc
+ )"
+PDEPEND="app-misc/ca-certificates"
+
+S="${WORKDIR}/${MY_P}"
+
+MULTILIB_WRAPPED_HEADERS=(
+ usr/include/openssl/opensslconf.h
+)
+
+src_prepare() {
+ # keep this in sync with app-misc/c_rehash
+ SSL_CNF_DIR="/etc/ssl"
+
+ # Make sure we only ever touch Makefile.org and avoid patching a file
+ # that gets blown away anyways by the Configure script in src_configure
+ rm -f Makefile
+
+ if ! use vanilla ; then
+ epatch "${FILESDIR}"/${PN}-1.0.0a-ldflags.patch #327421
+ epatch "${FILESDIR}"/${PN}-1.0.0d-windres.patch #373743
+ epatch "${FILESDIR}"/${PN}-1.0.2e-parallel-build.patch
+ epatch "${FILESDIR}"/${PN}-1.0.2a-parallel-obj-headers.patch
+ epatch "${FILESDIR}"/${PN}-1.0.2a-parallel-install-dirs.patch
+ epatch "${FILESDIR}"/${PN}-1.0.2a-parallel-symlinking.patch #545028
+ epatch "${FILESDIR}"/${PN}-1.0.2-ipv6.patch
+ epatch "${FILESDIR}"/${PN}-1.0.2a-x32-asm.patch #542618
+ epatch "${FILESDIR}"/${PN}-1.0.1p-default-source.patch #554338
+
+ epatch_user #332661
+ fi
+
+ if use cloudflare ; then
+ epatch "${FILESDIR}"/${PN}-1.0.2e-chacha20_poly1305_cf.patch
+ fi
+
+ # disable fips in the build
+ # make sure the man pages are suffixed #302165
+ # don't bother building man pages if they're disabled
+ sed -i \
+ -e '/DIRS/s: fips : :g' \
+ -e '/^MANSUFFIX/s:=.*:=ssl:' \
+ -e '/^MAKEDEPPROG/s:=.*:=$(CC):' \
+ -e $(has noman FEATURES \
+ && echo '/^install:/s:install_docs::' \
+ || echo '/^MANDIR=/s:=.*:='${EPREFIX}'/usr/share/man:') \
+ Makefile.org \
+ || die
+ # show the actual commands in the log
+ sed -i '/^SET_X/s:=.*:=set -x:' Makefile.shared
+
+ # since we're forcing $(CC) as makedep anyway, just fix
+ # the conditional as always-on
+ # helps clang (#417795), and versioned gcc (#499818)
+ sed -i 's/expr.*MAKEDEPEND.*;/true;/' util/domd || die
+
+ # quiet out unknown driver argument warnings since openssl
+ # doesn't have well-split CFLAGS and we're making it even worse
+ # and 'make depend' uses -Werror for added fun (#417795 again)
+ [[ ${CC} == *clang* ]] && append-flags -Qunused-arguments
+
+ # allow openssl to be cross-compiled
+ cp "${FILESDIR}"/gentoo.config-1.0.2 gentoo.config || die
+ chmod a+rx gentoo.config
+
+ append-flags -fno-strict-aliasing
+ append-flags $(test-flags-CC -Wa,--noexecstack)
+ append-cppflags -DOPENSSL_NO_BUF_FREELISTS
+
+ sed -i '1s,^:$,#!'${EPREFIX}'/usr/bin/perl,' Configure #141906
+ # The config script does stupid stuff to prompt the user. Kill it.
+ sed -i '/stty -icanon min 0 time 50; read waste/d' config || die
+ ./config --test-sanity || die "I AM NOT SANE"
+
+ multilib_copy_sources
+}
+
+multilib_src_configure() {
+ unset APPS #197996
+ unset SCRIPTS #312551
+ unset CROSS_COMPILE #311473
+
+ tc-export CC AR RANLIB RC
+
+ # Clean out patent-or-otherwise-encumbered code
+ # Camellia: Royalty Free http://en.wikipedia.org/wiki/Camellia_(cipher)
+ # IDEA: Expired http://en.wikipedia.org/wiki/International_Data_Encryption_Algorithm
+ # EC: ????????? ??/??/2015 http://en.wikipedia.org/wiki/Elliptic_Curve_Cryptography
+ # MDC2: Expired http://en.wikipedia.org/wiki/MDC-2
+ # RC5: Expired http://en.wikipedia.org/wiki/RC5
+
+ use_ssl() { usex $1 "enable-${2:-$1}" "no-${2:-$1}" " ${*:3}" ; }
+ echoit() { echo "$@" ; "$@" ; }
+
+ local krb5=$(has_version app-crypt/mit-krb5 && echo "MIT" || echo "Heimdal")
+
+ # See if our toolchain supports __uint128_t. If so, it's 64bit
+ # friendly and can use the nicely optimized code paths. #460790
+ local ec_nistp_64_gcc_128
+ # Disable it for now though #469976
+ #if ! use bindist ; then
+ # echo "__uint128_t i;" > "${T}"/128.c
+ # if ${CC} ${CFLAGS} -c "${T}"/128.c -o /dev/null >&/dev/null ; then
+ # ec_nistp_64_gcc_128="enable-ec_nistp_64_gcc_128"
+ # fi
+ #fi
+
+ local sslout=$(./gentoo.config)
+ einfo "Use configuration ${sslout:-(openssl knows best)}"
+ local config="Configure"
+ [[ -z ${sslout} ]] && config="config"
+
+ echoit \
+ ./${config} \
+ ${sslout} \
+ $(use cpu_flags_x86_sse2 || echo "no-sse2") \
+ enable-camellia \
+ $(use_ssl !bindist ec) \
+ ${ec_nistp_64_gcc_128} \
+ enable-idea \
+ enable-mdc2 \
+ enable-rc5 \
+ enable-tlsext \
+ $(use_ssl asm) \
+ $(use_ssl gmp gmp -lgmp) \
+ $(use_ssl kerberos krb5 --with-krb5-flavor=${krb5}) \
+ $(use_ssl rfc3779) \
+ $(use_ssl sctp) \
+ $(use_ssl tls-heartbeat heartbeats) \
+ $(use_ssl zlib) \
+ --prefix="${EPREFIX}"/usr \
+ --openssldir="${EPREFIX}"${SSL_CNF_DIR} \
+ --libdir=$(get_libdir) \
+ shared threads \
+ || die
+
+ # Clean out hardcoded flags that openssl uses
+ local CFLAG=$(grep ^CFLAG= Makefile | LC_ALL=C sed \
+ -e 's:^CFLAG=::' \
+ -e 's:-fomit-frame-pointer ::g' \
+ -e 's:-O[0-9] ::g' \
+ -e 's:-march=[-a-z0-9]* ::g' \
+ -e 's:-mcpu=[-a-z0-9]* ::g' \
+ -e 's:-m[a-z0-9]* ::g' \
+ )
+ sed -i \
+ -e "/^CFLAG/s|=.*|=${CFLAG} ${CFLAGS}|" \
+ -e "/^SHARED_LDFLAGS=/s|$| ${LDFLAGS}|" \
+ Makefile || die
+}
+
+multilib_src_compile() {
+ # depend is needed to use $confopts; it also doesn't matter
+ # that it's -j1 as the code itself serializes subdirs
+ emake -j1 depend
+ emake all
+ # rehash is needed to prep the certs/ dir; do this
+ # separately to avoid parallel build issues.
+ emake rehash
+}
+
+multilib_src_test() {
+ emake -j1 test
+}
+
+multilib_src_install() {
+ emake INSTALL_PREFIX="${D}" install
+}
+
+multilib_src_install_all() {
+ # openssl installs perl version of c_rehash by default, but
+ # we provide a shell version via app-misc/c_rehash
+ rm "${ED}"/usr/bin/c_rehash || die
+
+ dodoc CHANGES* FAQ NEWS README doc/*.txt doc/c-indentation.el
+ dohtml -r doc/*
+ use rfc3779 && dodoc engines/ccgost/README.gost
+
+ # This is crappy in that the static archives are still built even
+ # when USE=static-libs. But this is due to a failing in the openssl
+ # build system: the static archives are built as PIC all the time.
+ # Only way around this would be to manually configure+compile openssl
+ # twice; once with shared lib support enabled and once without.
+ use static-libs || rm -f "${ED}"/usr/lib*/lib*.a
+
+ # create the certs directory
+ dodir ${SSL_CNF_DIR}/certs
+ cp -RP certs/* "${ED}"${SSL_CNF_DIR}/certs/ || die
+ rm -r "${ED}"${SSL_CNF_DIR}/certs/{demo,expired}
+
+ # Namespace openssl programs to prevent conflicts with other man pages
+ cd "${ED}"/usr/share/man
+ local m d s
+ for m in $(find . -type f | xargs grep -L '#include') ; do
+ d=${m%/*} ; d=${d#./} ; m=${m##*/}
+ [[ ${m} == openssl.1* ]] && continue
+ [[ -n $(find -L ${d} -type l) ]] && die "erp, broken links already!"
+ mv ${d}/{,ssl-}${m}
+ # fix up references to renamed man pages
+ sed -i '/^[.]SH "SEE ALSO"/,/^[.]/s:\([^(, ]*(1)\):ssl-\1:g' ${d}/ssl-${m}
+ ln -s ssl-${m} ${d}/openssl-${m}
+ # locate any symlinks that point to this man page ... we assume
+ # that any broken links are due to the above renaming
+ for s in $(find -L ${d} -type l) ; do
+ s=${s##*/}
+ rm -f ${d}/${s}
+ ln -s ssl-${m} ${d}/ssl-${s}
+ ln -s ssl-${s} ${d}/openssl-${s}
+ done
+ done
+ [[ -n $(find -L ${d} -type l) ]] && die "broken manpage links found :("
+
+ dodir /etc/sandbox.d #254521
+ echo 'SANDBOX_PREDICT="/dev/crypto"' > "${ED}"/etc/sandbox.d/10openssl
+
+ diropts -m0700
+ keepdir ${SSL_CNF_DIR}/private
+}
+
+pkg_preinst() {
+ has_version ${CATEGORY}/${PN}:0.9.8 && return 0
+ preserve_old_lib /usr/$(get_libdir)/lib{crypto,ssl}.so.0.9.8
+}
+
+pkg_postinst() {
+ ebegin "Running 'c_rehash ${EROOT%/}${SSL_CNF_DIR}/certs/' to rebuild hashes #333069"
+ c_rehash "${EROOT%/}${SSL_CNF_DIR}/certs" >/dev/null
+ eend $?
+
+ has_version ${CATEGORY}/${PN}:0.9.8 && return 0
+ preserve_old_lib_notify /usr/$(get_libdir)/lib{crypto,ssl}.so.0.9.8
+}