[openssl-commits] [openssl] master update

Andy Polyakov appro at openssl.org
Thu Dec 10 11:16:07 UTC 2015


The branch master has been updated
       via  c7b5b9f4b1ec24743da20926f50418ba9fa92e87 (commit)
       via  48f14845551c530ed42834d8034d53222d355175 (commit)
       via  a76ba82ccbfee6df5aa86ba2a275b713f3e0f239 (commit)
       via  bd3385d84505eeb552a6125415607785f63c6d2d (commit)
       via  eb85cb8632ad5d868a5634b3ce18846ae351c380 (commit)
       via  bd989745b7a4796dceff89d93b6b7ac1561c6227 (commit)
       via  f6b9427923dd275ea4149a73f841dbcee079ace3 (commit)
       via  72bb2f64fc67dc644f302a07953900becced011f (commit)
       via  7dcb21869bec05d574d55e4c29daa5d58480d2a1 (commit)
      from  a0ffedaf7bb7b457b42108b8819d00e64003b3a9 (commit)


- Log -----------------------------------------------------------------
commit c7b5b9f4b1ec24743da20926f50418ba9fa92e87
Author: Andy Polyakov <appro at openssl.org>
Date:   Thu Dec 10 00:03:06 2015 +0100

    make update.
    
    Reviewed-by: Richard Levitte <levitte at openssl.org>

commit 48f14845551c530ed42834d8034d53222d355175
Author: Andy Polyakov <appro at openssl.org>
Date:   Wed Dec 9 23:02:11 2015 +0100

    Configure: make no-chacha and no-poly1305 work.
    
    Reviewed-by: Richard Levitte <levitte at openssl.org>

commit a76ba82ccbfee6df5aa86ba2a275b713f3e0f239
Author: Andy Polyakov <appro at openssl.org>
Date:   Wed Dec 9 21:47:00 2015 +0100

    Wire ChaCha20-Poly1305 to TLS.
    
    Reviewed-by: Richard Levitte <levitte at openssl.org>

commit bd3385d84505eeb552a6125415607785f63c6d2d
Author: Andy Polyakov <appro at openssl.org>
Date:   Wed Dec 9 21:36:19 2015 +0100

    evp/c_allc.c: wire ChaCha20-Poly1305 and add tests.
    
    Reviewed-by: Richard Levitte <levitte at openssl.org>

commit eb85cb8632ad5d868a5634b3ce18846ae351c380
Author: Andy Polyakov <appro at openssl.org>
Date:   Wed Dec 9 21:35:30 2015 +0100

    test/evp_test.c: allow generic AEAD ciphers to be tested.
    
    Reviewed-by: Richard Levitte <levitte at openssl.org>

commit bd989745b7a4796dceff89d93b6b7ac1561c6227
Author: Andy Polyakov <appro at openssl.org>
Date:   Wed Dec 9 21:30:56 2015 +0100

    crypto/evp: add e_chacha20_poly1305.c.
    
    Reviewed-by: Richard Levitte <levitte at openssl.org>

commit f6b9427923dd275ea4149a73f841dbcee079ace3
Author: Andy Polyakov <appro at openssl.org>
Date:   Wed Dec 9 21:18:00 2015 +0100

    evp/evp_enc.c: allow EVP_CIPHER.ctx_size to be 0.
    
    In such case it would be EVP_CIPHER.cleanup's reponsibility to wipe
    EVP_CIPHEX_CTX.cipher_data.
    
    Reviewed-by: Richard Levitte <levitte at openssl.org>

commit 72bb2f64fc67dc644f302a07953900becced011f
Author: Andy Polyakov <appro at openssl.org>
Date:   Wed Dec 9 21:15:28 2015 +0100

    Add ChaCha20-Poly1305 and ChaCha20 NIDs.
    
    Reviewed-by: Richard Levitte <levitte at openssl.org>

commit 7dcb21869bec05d574d55e4c29daa5d58480d2a1
Author: Andy Polyakov <appro at openssl.org>
Date:   Wed Dec 9 21:11:49 2015 +0100

    Add reference ChaCha20 and Poly1305 implementations.
    
    Reviewed-by: Emilia Käsper <emilia at openssl.org>
    Reviewed-by: Richard Levitte <levitte at openssl.org>
    Reviewed-by: Kurt Roeckx <kurt at openssl.org>

-----------------------------------------------------------------------

Summary of changes:
 Configure                                          |   2 +
 Makefile.org                                       |   4 +-
 crypto/{whrlpool => chacha}/Makefile               |  32 +-
 crypto/chacha/chacha_enc.c                         | 157 ++++
 crypto/evp/Makefile                                |  26 +-
 crypto/evp/c_allc.c                                |   7 +
 crypto/evp/e_chacha20_poly1305.c                   | 490 ++++++++++++
 crypto/evp/evp_enc.c                               |   8 +-
 crypto/evp/evp_err.c                               |  11 +-
 ssl/ssl_utst.c => crypto/include/internal/chacha.h |  56 +-
 .../include/internal/poly1305.h                    |  29 +-
 crypto/objects/obj_dat.h                           |  12 +-
 crypto/objects/obj_mac.num                         |   2 +
 crypto/objects/objects.txt                         |   2 +
 crypto/{whrlpool => poly1305}/Makefile             |  32 +-
 crypto/poly1305/poly1305.c                         | 879 +++++++++++++++++++++
 include/openssl/evp.h                              |   8 +
 include/openssl/obj_mac.h                          |   8 +
 include/openssl/ssl.h                              |   1 +
 include/openssl/tls1.h                             |  18 +
 ssl/s3_lib.c                                       | 113 +++
 ssl/ssl_algs.c                                     |   3 +
 ssl/ssl_ciph.c                                     |   4 +-
 ssl/ssl_locl.h                                     |   1 +
 ssl/t1_trce.c                                      |   7 +
 test/evp_test.c                                    |   2 +
 test/evptests.txt                                  |  65 ++
 util/libeay.num                                    |   7 +
 util/mkdef.pl                                      |   9 +-
 29 files changed, 1894 insertions(+), 101 deletions(-)
 copy crypto/{whrlpool => chacha}/Makefile (57%)
 create mode 100644 crypto/chacha/chacha_enc.c
 create mode 100644 crypto/evp/e_chacha20_poly1305.c
 copy ssl/ssl_utst.c => crypto/include/internal/chacha.h (63%)
 copy ssl/ssl_utst.c => crypto/include/internal/poly1305.h (84%)
 copy crypto/{whrlpool => poly1305}/Makefile (57%)
 create mode 100644 crypto/poly1305/poly1305.c

diff --git a/Configure b/Configure
index 9473452..09998d9 100755
--- a/Configure
+++ b/Configure
@@ -812,6 +812,7 @@ my @disablables = (
     "camellia",
     "capieng",
     "cast",
+    "chacha",
     "cmac",
     "cms",
     "comp",
@@ -845,6 +846,7 @@ my @disablables = (
     "nextprotoneg",
     "ocb",
     "ocsp",
+    "poly1305",
     "posix-io",
     "psk",
     "rc2",
diff --git a/Makefile.org b/Makefile.org
index 8f64a98..cadcaad 100644
--- a/Makefile.org
+++ b/Makefile.org
@@ -138,8 +138,8 @@ INSTALL_SUBS= engines apps tools
 # dirs in crypto to build
 SDIRS=  \
 	objects \
-	md2 md4 md5 sha mdc2 hmac ripemd whrlpool \
-	des aes rc2 rc4 rc5 idea bf cast camellia seed modes \
+	md2 md4 md5 sha mdc2 hmac ripemd whrlpool poly1305 \
+	des aes rc2 rc4 rc5 idea bf cast camellia seed chacha modes \
 	bn ec rsa dsa dh dso engine \
 	buffer bio stack lhash rand err \
 	evp asn1 pem x509 x509v3 conf txt_db pkcs7 pkcs12 comp ocsp ui \
diff --git a/crypto/whrlpool/Makefile b/crypto/chacha/Makefile
similarity index 57%
copy from crypto/whrlpool/Makefile
copy to crypto/chacha/Makefile
index aafb467..cd249b1 100644
--- a/crypto/whrlpool/Makefile
+++ b/crypto/chacha/Makefile
@@ -1,32 +1,31 @@
 #
-# crypto/whrlpool/Makefile
+# OpenSSL/crypto/chacha/Makefile
 #
 
-DIR=	whrlpool
+DIR=	chacha
 TOP=	../..
 CC=	cc
-CPP=	$(CC) -E
+CPP=    $(CC) -E
 INCLUDES=
 CFLAG=-g
-MAKEFILE=	Makefile
 AR=		ar r
 
-WP_ASM_OBJ=wp_block.o
+CHACHA_ENC=chacha_enc.o
 
 CFLAGS= $(INCLUDES) $(CFLAG)
 ASFLAGS= $(INCLUDES) $(ASFLAG)
 AFLAGS= $(ASFLAGS)
 
 GENERAL=Makefile
+TEST=chachatest.c
+APPS=
 
 LIB=$(TOP)/libcrypto.a
-LIBSRC=wp_dgst.c wp_block.c
-LIBOBJ=wp_dgst.o $(WP_ASM_OBJ)
+LIBSRC=chacha_enc.c
+LIBOBJ=$(CHACHA_ENC)
 
 SRC= $(LIBSRC)
 
-HEADER= wp_locl.h
-
 ALL=    $(GENERAL) $(SRC) $(HEADER)
 
 top:
@@ -39,14 +38,6 @@ lib:	$(LIBOBJ)
 	$(RANLIB) $(LIB) || echo Never mind.
 	@touch lib
 
-wp-mmx.s:	asm/wp-mmx.pl ../perlasm/x86asm.pl
-	$(PERL) asm/wp-mmx.pl $(PERLASM_SCHEME) $(CFLAGS) $(PROCESSOR) > $@
-
-wp-x86_64.s: asm/wp-x86_64.pl
-	$(PERL) asm/wp-x86_64.pl $(PERLASM_SCHEME) > $@
-
-$(LIBOBJ): $(LIBSRC)
-
 files:
 	$(PERL) $(TOP)/util/files.pl Makefile >> $(TOP)/MINFO
 
@@ -58,7 +49,7 @@ tests:
 lint:
 	lint -DLINT $(INCLUDES) $(SRC)>fluff
 
-update: depend
+update:	depend
 
 depend:
 	@[ -n "$(MAKEDEPEND)" ] # should be set by upper Makefile...
@@ -73,7 +64,4 @@ clean:
 
 # DO NOT DELETE THIS LINE -- make depend depends on it.
 
-wp_block.o: ../../include/openssl/e_os2.h ../../include/openssl/opensslconf.h
-wp_block.o: ../../include/openssl/whrlpool.h wp_block.c wp_locl.h
-wp_dgst.o: ../../include/openssl/e_os2.h ../../include/openssl/opensslconf.h
-wp_dgst.o: ../../include/openssl/whrlpool.h wp_dgst.c wp_locl.h
+chacha_enc.o: ../include/internal/chacha.h chacha_enc.c
diff --git a/crypto/chacha/chacha_enc.c b/crypto/chacha/chacha_enc.c
new file mode 100644
index 0000000..281a9be
--- /dev/null
+++ b/crypto/chacha/chacha_enc.c
@@ -0,0 +1,157 @@
+/* ====================================================================
+ * 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 at 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.
+ * ====================================================================
+ */
+
+/* Adapted from the public domain code by D. Bernstein from SUPERCOP. */
+
+#include <string.h>
+
+#include "internal/chacha.h"
+
+typedef unsigned int u32;
+typedef unsigned char u8;
+typedef union {
+    u32 u[16];
+    u8 c[64];
+} chacha_buf;
+
+# define ROTATE(v, n) (((v) << (n)) | ((v) >> (32 - (n))))
+
+# define U32TO8_LITTLE(p, v) do { \
+                                (p)[0] = (u8)(v >>  0); \
+                                (p)[1] = (u8)(v >>  8); \
+                                (p)[2] = (u8)(v >> 16); \
+                                (p)[3] = (u8)(v >> 24); \
+                                } while(0)
+
+/* QUARTERROUND updates a, b, c, d with a ChaCha "quarter" round. */
+# define QUARTERROUND(a,b,c,d) ( \
+                x[a] += x[b], x[d] = ROTATE((x[d] ^ x[a]),16), \
+                x[c] += x[d], x[b] = ROTATE((x[b] ^ x[c]),12), \
+                x[a] += x[b], x[d] = ROTATE((x[d] ^ x[a]), 8), \
+                x[c] += x[d], x[b] = ROTATE((x[b] ^ x[c]), 7)  )
+
+/* chacha_core performs 20 rounds of ChaCha on the input words in
+ * |input| and writes the 64 output bytes to |output|. */
+static void chacha20_core(chacha_buf *output, const u32 input[16])
+{
+    u32 x[16];
+    int i;
+    const union {
+        long one;
+        char little;
+    } is_endian = { 1 };
+
+    memcpy(x, input, sizeof(x));
+
+    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);
+    }
+
+    if (is_endian.little) {
+        for (i = 0; i < 16; ++i)
+            output->u[i] = x[i] + input[i];
+    } else {
+        for (i = 0; i < 16; ++i)
+            U32TO8_LITTLE(output->c + 4 * i, (x[i] + input[i]));
+    }
+}
+
+void ChaCha20_ctr32(unsigned char *out, const unsigned char *inp,
+                    size_t len, const unsigned int key[8],
+                    const unsigned int counter[4])
+{
+    u32 input[16];
+    chacha_buf buf;
+    size_t todo, i;
+
+    /* sigma constant "expand 32-byte k" in little-endian encoding */
+    input[0] = ((u32)'e') | ((u32)'x'<<8) | ((u32)'p'<<16) | ((u32)'a'<<24);
+    input[1] = ((u32)'n') | ((u32)'d'<<8) | ((u32)' '<<16) | ((u32)'3'<<24);
+    input[2] = ((u32)'2') | ((u32)'-'<<8) | ((u32)'b'<<16) | ((u32)'y'<<24);
+    input[3] = ((u32)'t') | ((u32)'e'<<8) | ((u32)' '<<16) | ((u32)'k'<<24);
+
+    input[4] = key[0];
+    input[5] = key[1];
+    input[6] = key[2];
+    input[7] = key[3];
+    input[8] = key[4];
+    input[9] = key[5];
+    input[10] = key[6];
+    input[11] = key[7];
+
+    input[12] = counter[0];
+    input[13] = counter[1];
+    input[14] = counter[2];
+    input[15] = counter[3];
+
+    while (len > 0) {
+        todo = sizeof(buf);
+        if (len < todo)
+            todo = len;
+
+        chacha20_core(&buf, input);
+
+        for (i = 0; i < todo; i++)
+            out[i] = inp[i] ^ buf.c[i];
+        out += todo;
+        inp += todo;
+        len -= todo;
+
+        /* advance counter */
+        if (++input[12] == 0)
+            input[13]++;
+    }
+}
diff --git a/crypto/evp/Makefile b/crypto/evp/Makefile
index dbaf58a..4120158 100644
--- a/crypto/evp/Makefile
+++ b/crypto/evp/Makefile
@@ -26,7 +26,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 scrypt.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_chacha20_poly1305.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\
@@ -39,7 +40,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 scrypt.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_chacha20_poly1305.o
 
 SRC= $(LIBSRC)
 
@@ -248,6 +250,26 @@ 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 ../include/internal/cryptlib.h
 e_cast.o: e_cast.c evp_locl.h
+e_chacha20_poly1305.o: ../../e_os.h ../../include/openssl/asn1.h
+e_chacha20_poly1305.o: ../../include/openssl/bio.h
+e_chacha20_poly1305.o: ../../include/openssl/buffer.h
+e_chacha20_poly1305.o: ../../include/openssl/crypto.h
+e_chacha20_poly1305.o: ../../include/openssl/e_os2.h
+e_chacha20_poly1305.o: ../../include/openssl/err.h ../../include/openssl/evp.h
+e_chacha20_poly1305.o: ../../include/openssl/lhash.h
+e_chacha20_poly1305.o: ../../include/openssl/obj_mac.h
+e_chacha20_poly1305.o: ../../include/openssl/objects.h
+e_chacha20_poly1305.o: ../../include/openssl/opensslconf.h
+e_chacha20_poly1305.o: ../../include/openssl/opensslv.h
+e_chacha20_poly1305.o: ../../include/openssl/ossl_typ.h
+e_chacha20_poly1305.o: ../../include/openssl/safestack.h
+e_chacha20_poly1305.o: ../../include/openssl/stack.h
+e_chacha20_poly1305.o: ../../include/openssl/symhacks.h
+e_chacha20_poly1305.o: ../include/internal/chacha.h
+e_chacha20_poly1305.o: ../include/internal/cryptlib.h
+e_chacha20_poly1305.o: ../include/internal/evp_int.h
+e_chacha20_poly1305.o: ../include/internal/poly1305.h e_chacha20_poly1305.c
+e_chacha20_poly1305.o: evp_locl.h
 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/e_os2.h
diff --git a/crypto/evp/c_allc.c b/crypto/evp/c_allc.c
index ff4cffc..49f4c66 100644
--- a/crypto/evp/c_allc.c
+++ b/crypto/evp/c_allc.c
@@ -256,4 +256,11 @@ void OpenSSL_add_all_ciphers(void)
     EVP_add_cipher(EVP_camellia_192_ctr());
     EVP_add_cipher(EVP_camellia_256_ctr());
 #endif
+
+#ifndef OPENSSL_NO_CHACHA
+    EVP_add_cipher(EVP_chacha20());
+# ifndef OPENSSL_NO_POLY1305
+    EVP_add_cipher(EVP_chacha20_poly1305());
+# endif
+#endif
 }
diff --git a/crypto/evp/e_chacha20_poly1305.c b/crypto/evp/e_chacha20_poly1305.c
new file mode 100644
index 0000000..bce247d
--- /dev/null
+++ b/crypto/evp/e_chacha20_poly1305.c
@@ -0,0 +1,490 @@
+/* ====================================================================
+ * Copyright (c) 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 at 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 "internal/cryptlib.h"
+
+#ifndef OPENSSL_NO_CHACHA
+
+# include <openssl/evp.h>
+# include <openssl/objects.h>
+# include "evp_locl.h"
+# include "internal/evp_int.h"
+# include "internal/chacha.h"
+
+typedef struct {
+    union {
+        double align;   /* this ensures even sizeof(EVP_CHACHA_KEY)%8==0 */
+        unsigned int d[CHACHA_KEY_SIZE / 4];
+    } key;
+    unsigned int  counter[CHACHA_CTR_SIZE / 4];
+    unsigned char buf[CHACHA_BLK_SIZE];
+    unsigned int  partial_len;
+} EVP_CHACHA_KEY;
+
+#define data(ctx)   ((EVP_CHACHA_KEY *)(ctx)->cipher_data)
+
+static int chacha_init_key(EVP_CIPHER_CTX *ctx,
+                           const unsigned char user_key[CHACHA_KEY_SIZE],
+                           const unsigned char iv[CHACHA_CTR_SIZE], int enc)
+{
+    EVP_CHACHA_KEY *key = data(ctx);
+    unsigned int i;
+
+    if (user_key)
+        for (i = 0; i < CHACHA_KEY_SIZE; i+=4) {
+            key->key.d[i/4] = CHACHA_U8TOU32(user_key+i);
+        }
+
+    if (iv)
+        for (i = 0; i < CHACHA_CTR_SIZE; i+=4) {
+            key->counter[i/4] = CHACHA_U8TOU32(iv+i);
+        }
+
+    key->partial_len = 0;
+
+    return 1;
+}
+
+static int chacha_cipher(EVP_CIPHER_CTX * ctx, unsigned char *out,
+                         const unsigned char *inp, size_t len)
+{
+    EVP_CHACHA_KEY *key = data(ctx);
+    unsigned int n, rem, ctr32;
+
+    if ((n = key->partial_len)) {
+        while (len && n < CHACHA_BLK_SIZE) {
+            *out++ = *inp++ ^ key->buf[n++];
+            len--;
+        }
+        key->partial_len = n;
+
+        if (len == 0)
+            return 1;
+
+        if (n == CHACHA_BLK_SIZE) {
+            key->partial_len = 0;
+            key->counter[0]++;
+            if (key->counter[0] == 0)
+                key->counter[1]++;
+        }
+    }
+
+    rem = (unsigned int)(len % CHACHA_BLK_SIZE);
+    len -= rem;
+    ctr32 = key->counter[0];
+    while (len >= CHACHA_BLK_SIZE) {
+        size_t blocks = len / CHACHA_BLK_SIZE;
+        /*
+         * 1<<28 is just a not-so-small yet not-so-large number...
+         * Below condition is practically never met, but it has to
+         * be checked for code correctness.
+         */
+        if (sizeof(size_t)>sizeof(unsigned int) && blocks>(1U<<28))
+            blocks = (1U<<28);
+
+        /*
+         * As ChaCha20_ctr32 operates on 32-bit counter, caller
+         * has to handle overflow. 'if' below detects the
+         * overflow, which is then handled by limiting the
+         * amount of blocks to the exact overflow point...
+         */
+        ctr32 += (unsigned int)blocks;
+        if (ctr32 < blocks) {
+            blocks -= ctr32;
+            ctr32 = 0;
+        }
+        blocks *= CHACHA_BLK_SIZE;
+        ChaCha20_ctr32(out, inp, blocks, key->key.d, key->counter);
+        len -= blocks;
+        inp += blocks;
+        out += blocks;
+
+        key->counter[0] = ctr32;
+        if (ctr32 == 0) key->counter[1]++;
+    }
+
+    if (rem) {
+        memset(key->buf, 0, sizeof(key->buf));
+        ChaCha20_ctr32(key->buf, key->buf, CHACHA_BLK_SIZE,
+                       key->key.d, key->counter);
+        for (n = 0; n < rem; n++)
+            out[n] = inp[n] ^ key->buf[n];
+        key->partial_len = rem;
+    }
+
+    return 1;
+}
+
+static const EVP_CIPHER chacha20 = {
+    NID_chacha20,
+    1,                      /* block_size */
+    CHACHA_KEY_SIZE,        /* key_len */
+    CHACHA_CTR_SIZE,        /* iv_len, 128-bit counter in the context */
+    0,                      /* flags */
+    chacha_init_key,
+    chacha_cipher,
+    NULL,
+    sizeof(EVP_CHACHA_KEY),
+    NULL,
+    NULL,
+    NULL,
+    NULL
+};
+
+const EVP_CIPHER *EVP_chacha20(void)
+{
+    return (&chacha20);
+}
+
+# ifndef OPENSSL_NO_POLY1305
+#  include "internal/poly1305.h"
+
+typedef struct {
+    EVP_CHACHA_KEY key;
+    unsigned int nonce[12/4];
+    unsigned char tag[POLY1305_BLOCK_SIZE];
+    struct { uint64_t aad, text; } len;
+    int aad, mac_inited, tag_len, nonce_len;
+    size_t tls_payload_length;
+} EVP_CHACHA_AEAD_CTX;
+
+#  define NO_TLS_PAYLOAD_LENGTH ((size_t)-1)
+#  define aead_data(ctx)        ((EVP_CHACHA_AEAD_CTX *)(ctx)->cipher_data)
+#  define POLY1305_ctx(actx)    ((POLY1305 *)(actx + 1))
+
+static int chacha20_poly1305_init_key(EVP_CIPHER_CTX *ctx,
+                                      const unsigned char *inkey,
+                                      const unsigned char *iv, int enc)
+{
+    EVP_CHACHA_AEAD_CTX *actx = aead_data(ctx);
+    unsigned char temp[CHACHA_CTR_SIZE];
+
+    if (!inkey && !iv)
+        return 1;
+
+    actx->len.aad = 0;
+    actx->len.text = 0;
+    actx->aad = 0;
+    actx->mac_inited = 0;
+    actx->tls_payload_length = NO_TLS_PAYLOAD_LENGTH;
+
+    /* pad on the left */
+    memset(temp, 0, sizeof(temp));
+    if (actx->nonce_len <= CHACHA_CTR_SIZE)
+        memcpy(temp + CHACHA_CTR_SIZE - actx->nonce_len, iv, actx->nonce_len);
+
+    chacha_init_key(ctx, inkey, temp, enc);
+
+    actx->nonce[0] = actx->key.counter[1];
+    actx->nonce[1] = actx->key.counter[2];
+    actx->nonce[2] = actx->key.counter[3];
+
+    return 1;
+}
+
+static int chacha20_poly1305_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
+                                    const unsigned char *in, size_t len)
+{
+    EVP_CHACHA_AEAD_CTX *actx = aead_data(ctx);
+    size_t rem, plen = actx->tls_payload_length;
+    static const unsigned char zero[POLY1305_BLOCK_SIZE] = { 0 };
+
+    if (!actx->mac_inited) {
+        actx->key.counter[0] = 0;
+        memset(actx->key.buf, 0, sizeof(actx->key.buf));
+        ChaCha20_ctr32(actx->key.buf, actx->key.buf, CHACHA_BLK_SIZE,
+                       actx->key.key.d, actx->key.counter);
+        Poly1305_Init(POLY1305_ctx(actx), actx->key.buf);
+        actx->key.counter[0] = 1;
+        actx->mac_inited = 1;
+    }
+
+    if (in) {                                   /* aad or text */
+        if (out == NULL) {                      /* aad */
+            Poly1305_Update(POLY1305_ctx(actx), in, len);
+            actx->len.aad += len;
+            actx->aad = 1;
+            return len;
+        } else {                                /* plain- or ciphertext */
+            if (actx->aad) {                    /* wrap up aad */
+                if ((rem = (size_t)actx->len.aad % POLY1305_BLOCK_SIZE))
+                    Poly1305_Update(POLY1305_ctx(actx), zero,
+                                    POLY1305_BLOCK_SIZE - rem);
+                actx->aad = 0;
+            }
+
+            actx->tls_payload_length = NO_TLS_PAYLOAD_LENGTH;
+            if (plen == NO_TLS_PAYLOAD_LENGTH)
+                plen = len;
+            else if (len != plen + POLY1305_BLOCK_SIZE)
+                return -1;
+
+            if (ctx->encrypt) {                 /* plaintext */
+                chacha_cipher(ctx, out, in, plen);
+                Poly1305_Update(POLY1305_ctx(actx), out, plen);
+                in += plen;
+                out += plen;
+                actx->len.text += plen;
+            } else {                            /* ciphertext */
+                Poly1305_Update(POLY1305_ctx(actx), in, plen);
+                chacha_cipher(ctx, out, in, plen);
+                in += plen;
+                out += plen;
+                actx->len.text += plen;
+            }
+        }
+    }
+    if (in == NULL                              /* explicit final */
+        || plen != len) {                       /* or tls mode */
+        const union {
+            long one;
+            char little;
+        } is_endian = { 1 };
+        unsigned char temp[POLY1305_BLOCK_SIZE];
+
+        if (actx->aad) {                        /* wrap up aad */
+            if ((rem = (size_t)actx->len.aad % POLY1305_BLOCK_SIZE))
+                Poly1305_Update(POLY1305_ctx(actx), zero,
+                                POLY1305_BLOCK_SIZE - rem);
+            actx->aad = 0;
+        }
+
+        if ((rem = (size_t)actx->len.text % POLY1305_BLOCK_SIZE))
+            Poly1305_Update(POLY1305_ctx(actx), zero,
+                            POLY1305_BLOCK_SIZE - rem);
+
+        if (is_endian.little) {
+            Poly1305_Update(POLY1305_ctx(actx),
+                            (unsigned char *)&actx->len, POLY1305_BLOCK_SIZE);
+        } else {
+            temp[0]  = (unsigned char)(actx->len.aad);
+            temp[1]  = (unsigned char)(actx->len.aad>>8);
+            temp[2]  = (unsigned char)(actx->len.aad>>16);
+            temp[3]  = (unsigned char)(actx->len.aad>>24);
+            temp[4]  = (unsigned char)(actx->len.aad>>32);
+            temp[5]  = (unsigned char)(actx->len.aad>>40);
+            temp[6]  = (unsigned char)(actx->len.aad>>48);
+            temp[7]  = (unsigned char)(actx->len.aad>>56);
+
+            temp[8]  = (unsigned char)(actx->len.text);
+            temp[9]  = (unsigned char)(actx->len.text>>8);
+            temp[10] = (unsigned char)(actx->len.text>>16);
+            temp[11] = (unsigned char)(actx->len.text>>24);
+            temp[12] = (unsigned char)(actx->len.text>>32);
+            temp[13] = (unsigned char)(actx->len.text>>40);
+            temp[14] = (unsigned char)(actx->len.text>>48);
+            temp[15] = (unsigned char)(actx->len.text>>56);
+
+            Poly1305_Update(POLY1305_ctx(actx), temp, POLY1305_BLOCK_SIZE);
+        }
+        Poly1305_Final(POLY1305_ctx(actx), ctx->encrypt ? actx->tag
+                                                        : temp);
+        actx->mac_inited = 0;
+
+        if (in != NULL && len != plen) {        /* tls mode */
+            if (ctx->encrypt) {
+                memcpy(out, actx->tag, POLY1305_BLOCK_SIZE);
+            } else {
+                if (CRYPTO_memcmp(temp, in, POLY1305_BLOCK_SIZE)) {
+                    memset(out, 0, plen);
+                    return -1;
+                }
+            }
+        }
+        else if (!ctx->encrypt) {
+            if (CRYPTO_memcmp(temp, actx->tag, actx->tag_len))
+                return -1;
+        }
+    }
+    return len;
+}
+
+static int chacha20_poly1305_cleanup(EVP_CIPHER_CTX *ctx)
+{
+    EVP_CHACHA_AEAD_CTX *actx = aead_data(ctx);
+    if (actx)
+        OPENSSL_cleanse(ctx->cipher_data, sizeof(*ctx) + Poly1305_ctx_size());
+    return 1;
+}
+
+static int chacha20_poly1305_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg,
+                                  void *ptr)
+{
+    EVP_CHACHA_AEAD_CTX *actx = aead_data(ctx);
+
+    switch(type) {
+    case EVP_CTRL_INIT:
+        if (actx == NULL)
+            actx = ctx->cipher_data
+                 = OPENSSL_zalloc(sizeof(*actx) + Poly1305_ctx_size());
+        if (actx == NULL) {
+            EVPerr(EVP_F_CHACHA20_POLY1305_CTRL, EVP_R_INITIALIZATION_ERROR);
+            return 0;
+        }
+        actx->len.aad = 0;
+        actx->len.text = 0;
+        actx->aad = 0;
+        actx->mac_inited = 0;
+        actx->tag_len = 0;
+        actx->nonce_len = 12;
+        actx->tls_payload_length = NO_TLS_PAYLOAD_LENGTH;
+        return 1;
+
+    case EVP_CTRL_COPY:
+        if (actx) {
+            if ((((EVP_CIPHER_CTX *)ptr)->cipher_data =
+                   BUF_memdup(actx,sizeof(*actx) + Poly1305_ctx_size()))
+                == NULL) {
+                EVPerr(EVP_F_CHACHA20_POLY1305_CTRL, EVP_R_COPY_ERROR);
+                return 0;
+            }
+        }
+        return 1;
+
+    case EVP_CTRL_AEAD_SET_IVLEN:
+        if (arg <= 0 || arg > CHACHA_CTR_SIZE)
+            return 0;
+        actx->nonce_len = arg;
+        return 1;
+
+    case EVP_CTRL_AEAD_SET_IV_FIXED:
+        if (arg != 12)
+            return 0;
+        actx->nonce[0] = actx->key.counter[1]
+                       = CHACHA_U8TOU32((unsigned char *)ptr);
+        actx->nonce[1] = actx->key.counter[2]
+                       = CHACHA_U8TOU32((unsigned char *)ptr+4);
+        actx->nonce[2] = actx->key.counter[3]
+                       = CHACHA_U8TOU32((unsigned char *)ptr+8);
+        return 1;
+
+    case EVP_CTRL_AEAD_SET_TAG:
+        if (arg <= 0 || arg > POLY1305_BLOCK_SIZE)
+            return 0;
+        if (ptr != NULL) {
+            memcpy(actx->tag, ptr, arg);
+            actx->tag_len = arg;
+        }
+        return 1;
+
+    case EVP_CTRL_AEAD_GET_TAG:
+        if (arg <= 0 || arg > POLY1305_BLOCK_SIZE || !ctx->encrypt)
+            return 0;
+        memcpy(ptr, actx->tag, arg);
+        return 1;
+
+    case EVP_CTRL_AEAD_TLS1_AAD:
+        if (arg != EVP_AEAD_TLS1_AAD_LEN)
+            return 0;
+        {
+            unsigned int len;
+            unsigned char temp[POLY1305_BLOCK_SIZE];
+
+            /*
+             * compose padded aad
+             */
+            memset(temp, 0, sizeof(temp));
+            memcpy(temp, ptr, EVP_AEAD_TLS1_AAD_LEN);
+
+            len = temp[EVP_AEAD_TLS1_AAD_LEN - 2] << 8 |
+                  temp[EVP_AEAD_TLS1_AAD_LEN - 1];
+            if (!ctx->encrypt) {
+                len -= POLY1305_BLOCK_SIZE;     /* discount attached tag */
+                temp[EVP_AEAD_TLS1_AAD_LEN - 2] = (unsigned char)(len >> 8);
+                temp[EVP_AEAD_TLS1_AAD_LEN - 1] = (unsigned char)len;
+            }
+            actx->tls_payload_length = len;
+
+            /*
+             * merge record sequence number as per
+             * draft-ietf-tls-chacha20-poly1305-03
+             */
+            actx->key.counter[1] = actx->nonce[0];
+            actx->key.counter[2] = actx->nonce[1] ^ CHACHA_U8TOU32(temp);
+            actx->key.counter[3] = actx->nonce[2] ^ CHACHA_U8TOU32(temp+4);
+            actx->mac_inited = 0;
+            chacha20_poly1305_cipher(ctx, NULL, temp, POLY1305_BLOCK_SIZE);
+            return POLY1305_BLOCK_SIZE;         /* tag length */
+        }
+
+    case EVP_CTRL_AEAD_SET_MAC_KEY:
+        /* no-op */
+        return 1;
+
+    default:
+        return -1;
+    }
+}
+
+static EVP_CIPHER chacha20_poly1305 = {
+    NID_chacha20_poly1305,
+    1,                  /* block_size */
+    CHACHA_KEY_SIZE,    /* key_len */
+    12,                 /* iv_len, 96-bit nonce in the context */
+    EVP_CIPH_FLAG_AEAD_CIPHER | EVP_CIPH_CUSTOM_IV |
+    EVP_CIPH_ALWAYS_CALL_INIT | EVP_CIPH_CTRL_INIT |
+    EVP_CIPH_CUSTOM_COPY | EVP_CIPH_FLAG_CUSTOM_CIPHER,
+    chacha20_poly1305_init_key,
+    chacha20_poly1305_cipher,
+    chacha20_poly1305_cleanup,
+    0,          /* 0 moves context-specific structure allocation to ctrl */
+    NULL,       /* set_asn1_parameters */
+    NULL,       /* get_asn1_parameters */
+    chacha20_poly1305_ctrl,
+    NULL        /* app_data */
+};
+
+const EVP_CIPHER *EVP_chacha20_poly1305(void)
+{
+    return(&chacha20_poly1305);
+}
+# endif
+#endif
diff --git a/crypto/evp/evp_enc.c b/crypto/evp/evp_enc.c
index 7ef0dd8..6523bf1 100644
--- a/crypto/evp/evp_enc.c
+++ b/crypto/evp/evp_enc.c
@@ -105,10 +105,8 @@ int EVP_CipherInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
      * previous handle, re-querying for an ENGINE, and having a
      * reinitialisation, when it may all be unecessary.
      */
-    if (ctx->engine && ctx->cipher && (!cipher ||
-                                       (cipher
-                                        && (cipher->nid ==
-                                            ctx->cipher->nid))))
+    if (ctx->engine && ctx->cipher
+        && (!cipher || (cipher && (cipher->nid == ctx->cipher->nid))))
         goto skip_to_init;
 #endif
     if (cipher) {
@@ -531,7 +529,7 @@ int EVP_CIPHER_CTX_cleanup(EVP_CIPHER_CTX *c)
         if (c->cipher->cleanup && !c->cipher->cleanup(c))
             return 0;
         /* Cleanse cipher context data */
-        if (c->cipher_data)
+        if (c->cipher_data && c->cipher->ctx_size)
             OPENSSL_cleanse(c->cipher_data, c->cipher->ctx_size);
     }
     OPENSSL_free(c->cipher_data);
diff --git a/crypto/evp/evp_err.c b/crypto/evp/evp_err.c
index e63b9a0..94e32b5 100644
--- a/crypto/evp/evp_err.c
+++ b/crypto/evp/evp_err.c
@@ -78,6 +78,7 @@ static ERR_STRING_DATA EVP_str_functs[] = {
     {ERR_FUNC(EVP_F_AES_XTS_CIPHER), "AES_XTS_CIPHER"},
     {ERR_FUNC(EVP_F_ALG_MODULE_INIT), "alg_module_init"},
     {ERR_FUNC(EVP_F_CAMELLIA_INIT_KEY), "camellia_init_key"},
+    {ERR_FUNC(EVP_F_CHACHA20_POLY1305_CTRL), "chacha20_poly1305_ctrl"},
     {ERR_FUNC(EVP_F_CMAC_INIT), "CMAC_INIT"},
     {ERR_FUNC(EVP_F_CMLL_T4_INIT_KEY), "cmll_t4_init_key"},
     {ERR_FUNC(EVP_F_D2I_PKEY), "D2I_PKEY"},
@@ -167,10 +168,10 @@ static ERR_STRING_DATA EVP_str_reasons[] = {
     {ERR_REASON(EVP_R_BN_DECODE_ERROR), "bn decode error"},
     {ERR_REASON(EVP_R_BN_PUBKEY_ERROR), "bn pubkey error"},
     {ERR_REASON(EVP_R_BUFFER_TOO_SMALL), "buffer too small"},
-    {ERR_REASON(EVP_R_CAMELLIA_KEY_SETUP_FAILED),
-     "camellia key setup failed"},
+    {ERR_REASON(EVP_R_CAMELLIA_KEY_SETUP_FAILED), "camellia key setup failed"},
     {ERR_REASON(EVP_R_CIPHER_PARAMETER_ERROR), "cipher parameter error"},
     {ERR_REASON(EVP_R_COMMAND_NOT_SUPPORTED), "command not supported"},
+    {ERR_REASON(EVP_R_COPY_ERROR), "copy error"},
     {ERR_REASON(EVP_R_CTRL_NOT_IMPLEMENTED), "ctrl not implemented"},
     {ERR_REASON(EVP_R_CTRL_OPERATION_NOT_IMPLEMENTED),
      "ctrl operation not implemented"},
@@ -190,8 +191,7 @@ static ERR_STRING_DATA EVP_str_reasons[] = {
     {ERR_REASON(EVP_R_EXPECTING_A_ECDSA_KEY), "expecting a ecdsa key"},
     {ERR_REASON(EVP_R_EXPECTING_A_EC_KEY), "expecting a ec key"},
     {ERR_REASON(EVP_R_FIPS_MODE_NOT_SUPPORTED), "fips mode not supported"},
-    {ERR_REASON(EVP_R_ILLEGAL_SCRYPT_PARAMETERS),
-     "illegal scrypt parameters"},
+    {ERR_REASON(EVP_R_ILLEGAL_SCRYPT_PARAMETERS), "illegal scrypt parameters"},
     {ERR_REASON(EVP_R_INITIALIZATION_ERROR), "initialization error"},
     {ERR_REASON(EVP_R_INPUT_NOT_INITIALIZED), "input not initialized"},
     {ERR_REASON(EVP_R_INVALID_DIGEST), "invalid digest"},
@@ -217,8 +217,7 @@ static ERR_STRING_DATA EVP_str_reasons[] = {
     {ERR_REASON(EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE),
      "operation not supported for this keytype"},
     {ERR_REASON(EVP_R_OPERATON_NOT_INITIALIZED), "operaton not initialized"},
-    {ERR_REASON(EVP_R_PKCS8_UNKNOWN_BROKEN_TYPE),
-     "pkcs8 unknown broken type"},
+    {ERR_REASON(EVP_R_PKCS8_UNKNOWN_BROKEN_TYPE), "pkcs8 unknown broken type"},
     {ERR_REASON(EVP_R_PRIVATE_KEY_DECODE_ERROR), "private key decode error"},
     {ERR_REASON(EVP_R_PRIVATE_KEY_ENCODE_ERROR), "private key encode error"},
     {ERR_REASON(EVP_R_PUBLIC_KEY_NOT_RSA), "public key not rsa"},
diff --git a/ssl/ssl_utst.c b/crypto/include/internal/chacha.h
similarity index 63%
copy from ssl/ssl_utst.c
copy to crypto/include/internal/chacha.h
index 53bdde3..98787d3 100644
--- a/ssl/ssl_utst.c
+++ b/crypto/include/internal/chacha.h
@@ -1,8 +1,3 @@
-/* ssl_utst.c */
-/*
- * Written by Dr Stephen N Henson (steve at openssl.org) for the OpenSSL
- * project.
- */
 /* ====================================================================
  * Copyright (c) 2014 The OpenSSL Project.  All rights reserved.
  *
@@ -53,20 +48,47 @@
  *
  */
 
-#include "ssl_locl.h"
+#ifndef HEADER_CHACHA_H
+#define HEADER_CHACHA_H
+
+#include <stddef.h>
 
-#ifndef OPENSSL_NO_UNIT_TEST
+#ifdef __cplusplus
+extern "C" {
+#endif
 
-static const struct openssl_ssl_test_functions ssl_test_functions = {
-    ssl_init_wbio_buffer,
-    ssl3_setup_buffers,
-    tls1_process_heartbeat,
-    dtls1_process_heartbeat
-};
+# ifdef OPENSSL_NO_CHACHA
+#  error CHACHA is disabled.
+# endif
 
-const struct openssl_ssl_test_functions *SSL_test_functions(void)
-{
-    return &ssl_test_functions;
-}
+/*
+ * ChaCha20_ctr32 encrypts |len| bytes from |inp| with the given key and
+ * nonce and writes the result to |out|, which may be equal to |inp|.
+ * The |key| is not 32 bytes of verbatim key material though, but the
+ * said material collected into 8 32-bit elements array in host byte
+ * order. Same approach applies to nonce: the |counter| argument is
+ * pointer to concatenated nonce and counter values collected into 4
+ * 32-bit elements. This, passing crypto material collected into 32-bit
+ * elements as opposite to passing verbatim byte vectors, is chosen for
+ * efficiency in multi-call scenarios.
+ */
+void ChaCha20_ctr32(unsigned char *out, const unsigned char *inp,
+                    size_t len, const unsigned int key[8],
+                    const unsigned int counter[4]);
+/*
+ * You can notice that there is no key setup procedure. Because it's
+ * as trivial as collecting bytes into 32-bit elements, it's reckoned
+ * that below macro is sufficient.
+ */
+#define CHACHA_U8TOU32(p)  ( \
+                ((unsigned int)(p)[0])     | ((unsigned int)(p)[1]<<8) | \
+                ((unsigned int)(p)[2]<<16) | ((unsigned int)(p)[3]<<24)  )
 
+#define CHACHA_KEY_SIZE		32
+#define CHACHA_CTR_SIZE		16
+#define CHACHA_BLK_SIZE		64
+
+#ifdef __cplusplus
+}
+#endif
 #endif
diff --git a/ssl/ssl_utst.c b/crypto/include/internal/poly1305.h
similarity index 84%
copy from ssl/ssl_utst.c
copy to crypto/include/internal/poly1305.h
index 53bdde3..b6db325 100644
--- a/ssl/ssl_utst.c
+++ b/crypto/include/internal/poly1305.h
@@ -1,8 +1,3 @@
-/* ssl_utst.c */
-/*
- * Written by Dr Stephen N Henson (steve at openssl.org) for the OpenSSL
- * project.
- */
 /* ====================================================================
  * Copyright (c) 2014 The OpenSSL Project.  All rights reserved.
  *
@@ -52,21 +47,17 @@
  * ====================================================================
  *
  */
+#include <stddef.h>
 
-#include "ssl_locl.h"
-
-#ifndef OPENSSL_NO_UNIT_TEST
+#ifdef OPENSSL_NO_POLY1305
+# error POLY1305 is disabled.
+#endif
 
-static const struct openssl_ssl_test_functions ssl_test_functions = {
-    ssl_init_wbio_buffer,
-    ssl3_setup_buffers,
-    tls1_process_heartbeat,
-    dtls1_process_heartbeat
-};
+#define POLY1305_BLOCK_SIZE 16
 
-const struct openssl_ssl_test_functions *SSL_test_functions(void)
-{
-    return &ssl_test_functions;
-}
+typedef struct poly1305_context POLY1305;
 
-#endif
+size_t Poly1305_ctx_size(void);
+void Poly1305_Init(POLY1305 *ctx, const unsigned char key[32]);
+void Poly1305_Update(POLY1305 *ctx, const unsigned char *inp, size_t len);
+void Poly1305_Final(POLY1305 *ctx, unsigned char mac[16]);
diff --git a/crypto/objects/obj_dat.h b/crypto/objects/obj_dat.h
index 9fd2059..d1382a2 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 1018
-#define NUM_SN 1011
-#define NUM_LN 1011
+#define NUM_NID 1020
+#define NUM_SN 1013
+#define NUM_LN 1013
 #define NUM_OBJ 936
 
 static const unsigned char lvalues[6604]={
@@ -2667,6 +2667,8 @@ static const ASN1_OBJECT nid_objs[NUM_NID]={
 {"grasshopper-cbc","grasshopper-cbc",NID_grasshopper_cbc,0,NULL,0},
 {"grasshopper-cfb","grasshopper-cfb",NID_grasshopper_cfb,0,NULL,0},
 {"grasshopper-mac","grasshopper-mac",NID_grasshopper_mac,0,NULL,0},
+{"ChaCha20-Poly1305","chacha20-poly1305",NID_chacha20_poly1305,0,NULL,0},
+{"ChaCha20","chacha20",NID_chacha20,0,NULL,0},
 };
 
 static const unsigned int sn_objs[NUM_SN]={
@@ -2746,6 +2748,8 @@ static const unsigned int sn_objs[NUM_SN]={
 13,	/* "CN" */
 141,	/* "CRLReason" */
 417,	/* "CSPName" */
+1019,	/* "ChaCha20" */
+1018,	/* "ChaCha20-Poly1305" */
 367,	/* "CrlID" */
 391,	/* "DC" */
 31,	/* "DES-CBC" */
@@ -3973,6 +3977,8 @@ static const unsigned int ln_objs[NUM_LN]={
 677,	/* "certicom-arc" */
 517,	/* "certificate extensions" */
 883,	/* "certificateRevocationList" */
+1019,	/* "chacha20" */
+1018,	/* "chacha20-poly1305" */
 54,	/* "challengePassword" */
 407,	/* "characteristic-two-field" */
 395,	/* "clearance" */
diff --git a/crypto/objects/obj_mac.num b/crypto/objects/obj_mac.num
index ac8a1a2..2993f56 100644
--- a/crypto/objects/obj_mac.num
+++ b/crypto/objects/obj_mac.num
@@ -1015,3 +1015,5 @@ grasshopper_ofb		1014
 grasshopper_cbc		1015
 grasshopper_cfb		1016
 grasshopper_mac		1017
+chacha20_poly1305		1018
+chacha20		1019
diff --git a/crypto/objects/objects.txt b/crypto/objects/objects.txt
index 9f5f6c4..29517e3 100644
--- a/crypto/objects/objects.txt
+++ b/crypto/objects/objects.txt
@@ -1368,6 +1368,8 @@ kisa 1 6                : SEED-OFB      : seed-ofb
 			: AES-128-CBC-HMAC-SHA256	: aes-128-cbc-hmac-sha256
 			: AES-192-CBC-HMAC-SHA256	: aes-192-cbc-hmac-sha256
 			: AES-256-CBC-HMAC-SHA256	: aes-256-cbc-hmac-sha256
+			: ChaCha20-Poly1305		: chacha20-poly1305
+			: ChaCha20			: chacha20
 
 ISO-US 10046 2 1	: dhpublicnumber		: X9.42 DH
 
diff --git a/crypto/whrlpool/Makefile b/crypto/poly1305/Makefile
similarity index 57%
copy from crypto/whrlpool/Makefile
copy to crypto/poly1305/Makefile
index aafb467..366cd11 100644
--- a/crypto/whrlpool/Makefile
+++ b/crypto/poly1305/Makefile
@@ -1,32 +1,29 @@
 #
-# crypto/whrlpool/Makefile
+# OpenSSL/crypto/poly1305/Makefile
 #
 
-DIR=	whrlpool
+DIR=	poly1305
 TOP=	../..
 CC=	cc
-CPP=	$(CC) -E
+CPP=    $(CC) -E
 INCLUDES=
 CFLAG=-g
-MAKEFILE=	Makefile
 AR=		ar r
 
-WP_ASM_OBJ=wp_block.o
-
 CFLAGS= $(INCLUDES) $(CFLAG)
 ASFLAGS= $(INCLUDES) $(ASFLAG)
 AFLAGS= $(ASFLAGS)
 
 GENERAL=Makefile
+TEST=
+APPS=
 
 LIB=$(TOP)/libcrypto.a
-LIBSRC=wp_dgst.c wp_block.c
-LIBOBJ=wp_dgst.o $(WP_ASM_OBJ)
+LIBSRC=poly1305.c
+LIBOBJ=poly1305.o
 
 SRC= $(LIBSRC)
 
-HEADER= wp_locl.h
-
 ALL=    $(GENERAL) $(SRC) $(HEADER)
 
 top:
@@ -39,14 +36,6 @@ lib:	$(LIBOBJ)
 	$(RANLIB) $(LIB) || echo Never mind.
 	@touch lib
 
-wp-mmx.s:	asm/wp-mmx.pl ../perlasm/x86asm.pl
-	$(PERL) asm/wp-mmx.pl $(PERLASM_SCHEME) $(CFLAGS) $(PROCESSOR) > $@
-
-wp-x86_64.s: asm/wp-x86_64.pl
-	$(PERL) asm/wp-x86_64.pl $(PERLASM_SCHEME) > $@
-
-$(LIBOBJ): $(LIBSRC)
-
 files:
 	$(PERL) $(TOP)/util/files.pl Makefile >> $(TOP)/MINFO
 
@@ -58,7 +47,7 @@ tests:
 lint:
 	lint -DLINT $(INCLUDES) $(SRC)>fluff
 
-update: depend
+update:	depend
 
 depend:
 	@[ -n "$(MAKEDEPEND)" ] # should be set by upper Makefile...
@@ -73,7 +62,4 @@ clean:
 
 # DO NOT DELETE THIS LINE -- make depend depends on it.
 
-wp_block.o: ../../include/openssl/e_os2.h ../../include/openssl/opensslconf.h
-wp_block.o: ../../include/openssl/whrlpool.h wp_block.c wp_locl.h
-wp_dgst.o: ../../include/openssl/e_os2.h ../../include/openssl/opensslconf.h
-wp_dgst.o: ../../include/openssl/whrlpool.h wp_dgst.c wp_locl.h
+poly1305.o: ../include/internal/poly1305.h poly1305.c
diff --git a/crypto/poly1305/poly1305.c b/crypto/poly1305/poly1305.c
new file mode 100644
index 0000000..9a44f27
--- /dev/null
+++ b/crypto/poly1305/poly1305.c
@@ -0,0 +1,879 @@
+/* ====================================================================
+ * Copyright (c) 2015 The OpenSSL Project. All rights reserved.
+ *
+ * Rights for redistribution and usage in source and binary
+ * forms are granted according to the OpenSSL license.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "internal/poly1305.h"
+
+typedef void (*poly1305_blocks_f) (void *ctx, const unsigned char *inp,
+                                   size_t len, unsigned int padbit);
+typedef void (*poly1305_emit_f) (void *ctx, unsigned char mac[16],
+                                 const unsigned int nonce[4]);
+
+struct poly1305_context {
+    double opaque[24];  /* large enough to hold internal state, declared
+                         * 'double' to ensure at least 64-bit invariant
+                         * alignment across all platforms and
+                         * configurations */
+    unsigned int nonce[4];
+    unsigned char data[POLY1305_BLOCK_SIZE];
+    size_t num;
+    struct {
+        poly1305_blocks_f blocks;
+        poly1305_emit_f emit;
+    } func;
+};
+
+size_t Poly1305_ctx_size ()
+{
+    return sizeof(struct poly1305_context);
+}
+
+/* pick 32-bit unsigned integer in little endian order */
+static unsigned int U8TOU32(const unsigned char *p)
+{
+    return (((unsigned int)(p[0] & 0xff)) |
+            ((unsigned int)(p[1] & 0xff) << 8) |
+            ((unsigned int)(p[2] & 0xff) << 16) |
+            ((unsigned int)(p[3] & 0xff) << 24));
+}
+
+/*
+ * Implementations can be classified by amount of significant bits in
+ * words making up the multi-precision value, or in other words radix
+ * or base of numerical representation, e.g. base 2^64, base 2^32,
+ * base 2^26. Complementary characteristic is how wide is the result of
+ * multiplication of pair of digits, e.g. it would take 128 bits to
+ * accommodate multiplication result in base 2^64 case. These are used
+ * interchangeably. To describe implementation that is. But interface
+ * is designed to isolate this so that low-level primitives implemented
+ * in assembly can be self-contained/self-coherent.
+ */
+#ifndef POLY1305_ASM
+/*
+ * Even though there is __int128 reference implementation targeting
+ * 64-bit platforms provided below, it's not obvious that it's optimal
+ * choice for every one of them. Depending on instruction set overall
+ * amount of instructions can be comparable to one in __int64
+ * implementation. Amount of multiplication instructions would be lower,
+ * but not necessarily overall. And in out-of-order execution context,
+ * it is the latter that can be crucial...
+ *
+ * On related note. Poly1305 author, D. J. Bernstein, discusses and
+ * provides floating-point implementations of the algorithm in question.
+ * It made a lot of sense by the time of introduction, because most
+ * then-modern processors didn't have pipelined integer multiplier.
+ * [Not to mention that some had non-constant timing for integer
+ * multiplications.] Floating-point instructions on the other hand could
+ * be issued every cycle, which allowed to achieve better performance.
+ * Nowadays, with SIMD and/or out-or-order execution, shared or
+ * even emulated FPU, it's more complicated, and floating-point
+ * implementation is not necessarily optimal choice in every situation,
+ * rather contrary...
+ *
+ *                                              <appro at openssl.org>
+ */
+
+typedef unsigned int u32;
+
+/*
+ * poly1305_blocks processes a multiple of POLY1305_BLOCK_SIZE blocks
+ * of |inp| no longer than |len|. Behaviour for |len| not divisible by
+ * block size is unspecified in general case, even though in reference
+ * implementation the trailing chunk is simply ignored. Per algorithm
+ * specification, every input block, complete or last partial, is to be
+ * padded with a bit past most significant byte. The latter kind is then
+ * padded with zeros till block size. This last partial block padding
+ * is caller(*)'s responsibility, and because of this the last partial
+ * block is always processed with separate call with |len| set to
+ * POLY1305_BLOCK_SIZE and |padbit| to 0. In all other cases |padbit|
+ * should be set to 1 to perform implicit padding with 128th bit.
+ * poly1305_blocks does not actually check for this constraint though,
+ * it's caller(*)'s resposibility to comply.
+ *
+ * (*)  In the context "caller" is not application code, but higher
+ *      level Poly1305_* from this very module, so that quirks are
+ *      handled locally.
+ */
+static void
+poly1305_blocks(void *ctx, const unsigned char *inp, size_t len, u32 padbit);
+
+/*
+ * Type-agnostic "rip-off" from constant_time_locl.h
+ */
+# define CONSTANT_TIME_CARRY(a,b) ( \
+         (a ^ ((a ^ b) | ((a - b) ^ b))) >> (sizeof(a) * 8 - 1) \
+         )
+
+# if !defined(PEDANTIC) && \
+     (defined(__SIZEOF_INT128__) && __SIZEOF_INT128__==16) && \
+     (defined(__SIZEOF_LONG__) && __SIZEOF_LONG__==8)
+
+typedef unsigned long u64;
+typedef unsigned __int128 u128;
+
+typedef struct {
+    u64 h[3];
+    u64 r[2];
+} poly1305_internal;
+
+/* pick 32-bit unsigned integer in little endian order */
+static u64 U8TOU64(const unsigned char *p)
+{
+    return (((u64)(p[0] & 0xff)) |
+            ((u64)(p[1] & 0xff) << 8) |
+            ((u64)(p[2] & 0xff) << 16) |
+            ((u64)(p[3] & 0xff) << 24) |
+            ((u64)(p[4] & 0xff) << 32) |
+            ((u64)(p[5] & 0xff) << 40) |
+            ((u64)(p[6] & 0xff) << 48) |
+            ((u64)(p[7] & 0xff) << 56));
+}
+
+/* store a 32-bit unsigned integer in little endian */
+static void U64TO8(unsigned char *p, u64 v)
+{
+    p[0] = (unsigned char)((v) & 0xff);
+    p[1] = (unsigned char)((v >> 8) & 0xff);
+    p[2] = (unsigned char)((v >> 16) & 0xff);
+    p[3] = (unsigned char)((v >> 24) & 0xff);
+    p[4] = (unsigned char)((v >> 32) & 0xff);
+    p[5] = (unsigned char)((v >> 40) & 0xff);
+    p[6] = (unsigned char)((v >> 48) & 0xff);
+    p[7] = (unsigned char)((v >> 56) & 0xff);
+}
+
+static void poly1305_init(void *ctx, const unsigned char key[16])
+{
+    poly1305_internal *st = (poly1305_internal *) ctx;
+
+    /* h = 0 */
+    st->h[0] = 0;
+    st->h[1] = 0;
+    st->h[2] = 0;
+
+    /* r &= 0xffffffc0ffffffc0ffffffc0fffffff */
+    st->r[0] = U8TOU64(&key[0]) & 0x0ffffffc0fffffff;
+    st->r[1] = U8TOU64(&key[8]) & 0x0ffffffc0ffffffc;
+}
+
+static void
+poly1305_blocks(void *ctx, const unsigned char *inp, size_t len, u32 padbit)
+{
+    poly1305_internal *st = (poly1305_internal *)ctx;
+    u64 r0, r1;
+    u64 s1;
+    u64 h0, h1, h2, c;
+    u128 d0, d1;
+
+    r0 = st->r[0];
+    r1 = st->r[1];
+
+    s1 = r1 + (r1 >> 2);
+
+    h0 = st->h[0];
+    h1 = st->h[1];
+    h2 = st->h[2];
+
+    while (len >= POLY1305_BLOCK_SIZE) {
+        /* h += m[i] */
+        h0 = (u64)(d0 = (u128)h0 + U8TOU64(inp + 0));
+        h1 = (u64)(d1 = (u128)h1 + (d0 >> 64) + U8TOU64(inp + 8));
+        /*
+	 * padbit can be zero only when original len was
+	 * POLY1306_BLOCK_SIZE, but we don't check
+	 */
+        h2 += (u64)(d1 >> 64) + padbit;
+
+        /* h *= r "%" p, where "%" stands for "partial remainder" */
+        d0 = ((u128)h0 * r0) +
+             ((u128)h1 * s1);
+        d1 = ((u128)h0 * r1) +
+             ((u128)h1 * r0) +
+	     (h2 * s1);
+        h2 = (h2 * r0);
+
+        /* last reduction step: */
+        /* a) h2:h0 = h2<<128 + d1<<64 + d0 */
+        h0 = (u64)d0;
+        h1 = (u64)(d1 += d0 >> 64);
+        h2 += (u64)(d1 >> 64);
+        /* b) (h2:h0 += (h2:h0>>130) * 5) %= 2^130 */
+        c = (h2 >> 2) + (h2 & ~3UL);
+        h2 &= 3;
+        h0 += c;
+        h1 += (c = CONSTANT_TIME_CARRY(h0,c));   /* doesn't overflow */
+
+        inp += POLY1305_BLOCK_SIZE;
+        len -= POLY1305_BLOCK_SIZE;
+    }
+
+    st->h[0] = h0;
+    st->h[1] = h1;
+    st->h[2] = h2;
+}
+
+static void poly1305_emit(void *ctx, unsigned char mac[16],
+                          const u32 nonce[4])
+{
+    poly1305_internal *st = (poly1305_internal *) ctx;
+    u64 h0, h1, h2;
+    u64 g0, g1, g2;
+    u128 t;
+    u64 mask;
+
+    h0 = st->h[0];
+    h1 = st->h[1];
+    h2 = st->h[2];
+
+    /* compute h + -p */
+    g0 = (u64)(t = (u128)h0 + 5);
+    g1 = (u64)(t = (u128)h1 + (t >> 64));
+    g2 = h2 + (u64)(t >> 64);
+
+    /* if there was carry into 130th bit, h1:h0 = g1:g0 */
+    mask = 0 - (g2 >> 2);
+    g0 &= mask;
+    g1 &= mask;
+    mask = ~mask;
+    h0 = (h0 & mask) | g0;
+    h1 = (h1 & mask) | g1;
+
+    /* mac = (h + nonce) % (2^128) */
+    h0 = (u64)(t = (u128)h0 + nonce[0] + ((u64)nonce[1]<<32));
+    h1 = (u64)(t = (u128)h1 + nonce[2] + ((u64)nonce[3]<<32) + (t >> 64));
+
+    U64TO8(mac + 0, h0);
+    U64TO8(mac + 8, h1);
+}
+
+# else
+
+#  if defined(_WIN32) && !defined(__MINGW32__)
+typedef unsigned __int64 u64;
+#  elif defined(__arch64__)
+typedef unsigned long u64;
+#  else
+typedef unsigned long long u64;
+#  endif
+
+typedef struct {
+    u32 h[5];
+    u32 r[4];
+} poly1305_internal;
+
+/* store a 32-bit unsigned integer in little endian */
+static void U32TO8(unsigned char *p, unsigned int v)
+{
+    p[0] = (unsigned char)((v) & 0xff);
+    p[1] = (unsigned char)((v >> 8) & 0xff);
+    p[2] = (unsigned char)((v >> 16) & 0xff);
+    p[3] = (unsigned char)((v >> 24) & 0xff);
+}
+
+static void poly1305_init(void *ctx, const unsigned char key[16])
+{
+    poly1305_internal *st = (poly1305_internal *) ctx;
+
+    /* h = 0 */
+    st->h[0] = 0;
+    st->h[1] = 0;
+    st->h[2] = 0;
+    st->h[3] = 0;
+    st->h[4] = 0;
+
+    /* r &= 0xffffffc0ffffffc0ffffffc0fffffff */
+    st->r[0] = U8TOU32(&key[0]) & 0x0fffffff;
+    st->r[1] = U8TOU32(&key[4]) & 0x0ffffffc;
+    st->r[2] = U8TOU32(&key[8]) & 0x0ffffffc;
+    st->r[3] = U8TOU32(&key[12]) & 0x0ffffffc;
+}
+
+static void
+poly1305_blocks(void *ctx, const unsigned char *inp, size_t len, u32 padbit)
+{
+    poly1305_internal *st = (poly1305_internal *)ctx;
+    u32 r0, r1, r2, r3;
+    u32 s1, s2, s3;
+    u32 h0, h1, h2, h3, h4, c;
+    u64 d0, d1, d2, d3;
+
+    r0 = st->r[0];
+    r1 = st->r[1];
+    r2 = st->r[2];
+    r3 = st->r[3];
+
+    s1 = r1 + (r1 >> 2);
+    s2 = r2 + (r2 >> 2);
+    s3 = r3 + (r3 >> 2);
+
+    h0 = st->h[0];
+    h1 = st->h[1];
+    h2 = st->h[2];
+    h3 = st->h[3];
+    h4 = st->h[4];
+
+    while (len >= POLY1305_BLOCK_SIZE) {
+        /* h += m[i] */
+        h0 = (u32)(d0 = (u64)h0 + U8TOU32(inp + 0));
+        h1 = (u32)(d1 = (u64)h1 + (d0 >> 32) + U8TOU32(inp + 4));
+        h2 = (u32)(d2 = (u64)h2 + (d1 >> 32) + U8TOU32(inp + 8));
+        h3 = (u32)(d3 = (u64)h3 + (d2 >> 32) + U8TOU32(inp + 12));
+        h4 += (u32)(d3 >> 32) + padbit;
+
+        /* h *= r "%" p, where "%" stands for "partial remainder" */
+        d0 = ((u64)h0 * r0) +
+             ((u64)h1 * s3) +
+             ((u64)h2 * s2) +
+             ((u64)h3 * s1);
+        d1 = ((u64)h0 * r1) +
+             ((u64)h1 * r0) +
+             ((u64)h2 * s3) +
+             ((u64)h3 * s2) +
+             (h4 * s1);
+        d2 = ((u64)h0 * r2) +
+             ((u64)h1 * r1) +
+             ((u64)h2 * r0) +
+             ((u64)h3 * s3) +
+             (h4 * s2);
+        d3 = ((u64)h0 * r3) +
+             ((u64)h1 * r2) +
+             ((u64)h2 * r1) +
+             ((u64)h3 * r0) +
+             (h4 * s3);
+        h4 = (h4 * r0);
+
+        /* last reduction step: */
+        /* a) h4:h0 = h4<<128 + d3<<96 + d2<<64 + d1<<32 + d0 */
+        h0 = (u32)d0;
+        h1 = (u32)(d1 += d0 >> 32);
+        h2 = (u32)(d2 += d1 >> 32);
+        h3 = (u32)(d3 += d2 >> 32);
+        h4 += (u32)(d3 >> 32);
+        /* b) (h4:h0 += (h4:h0>>130) * 5) %= 2^130 */
+        c = (h4 >> 2) + (h4 & ~3U);
+        h4 &= 3;
+        h0 += c;
+        h1 += (c = CONSTANT_TIME_CARRY(h0,c));
+        h2 += (c = CONSTANT_TIME_CARRY(h1,c));
+        h3 += (c = CONSTANT_TIME_CARRY(h2,c));   /* doesn't overflow */
+
+        inp += POLY1305_BLOCK_SIZE;
+        len -= POLY1305_BLOCK_SIZE;
+    }
+
+    st->h[0] = h0;
+    st->h[1] = h1;
+    st->h[2] = h2;
+    st->h[3] = h3;
+    st->h[4] = h4;
+}
+
+static void poly1305_emit(void *ctx, unsigned char mac[16],
+                          const u32 nonce[4])
+{
+    poly1305_internal *st = (poly1305_internal *) ctx;
+    u32 h0, h1, h2, h3, h4;
+    u32 g0, g1, g2, g3, g4;
+    u64 t;
+    u32 mask;
+
+    h0 = st->h[0];
+    h1 = st->h[1];
+    h2 = st->h[2];
+    h3 = st->h[3];
+    h4 = st->h[4];
+
+    /* compute h + -p */
+    g0 = (u32)(t = (u64)h0 + 5);
+    g1 = (u32)(t = (u64)h1 + (t >> 32));
+    g2 = (u32)(t = (u64)h2 + (t >> 32));
+    g3 = (u32)(t = (u64)h3 + (t >> 32));
+    g4 = h4 + (u32)(t >> 32);
+
+    /* if there was carry into 130th bit, h3:h0 = g3:g0 */
+    mask = 0 - (g4 >> 2);
+    g0 &= mask;
+    g1 &= mask;
+    g2 &= mask;
+    g3 &= mask;
+    mask = ~mask;
+    h0 = (h0 & mask) | g0;
+    h1 = (h1 & mask) | g1;
+    h2 = (h2 & mask) | g2;
+    h3 = (h3 & mask) | g3;
+
+    /* mac = (h + nonce) % (2^128) */
+    h0 = (u32)(t = (u64)h0 + nonce[0]);
+    h1 = (u32)(t = (u64)h1 + (t >> 32) + nonce[1]);
+    h2 = (u32)(t = (u64)h2 + (t >> 32) + nonce[2]);
+    h3 = (u32)(t = (u64)h3 + (t >> 32) + nonce[3]);
+
+    U32TO8(mac + 0, h0);
+    U32TO8(mac + 4, h1);
+    U32TO8(mac + 8, h2);
+    U32TO8(mac + 12, h3);
+}
+# endif
+#else
+int poly1305_init(void *ctx, const unsigned char key[16], void *func);
+void poly1305_blocks(void *ctx, const unsigned char *inp, size_t len,
+                     unsigned int padbit);
+void poly1305_emit(void *ctx, unsigned char mac[16],
+                   const unsigned int nonce[4]);
+#endif
+
+void Poly1305_Init(POLY1305 *ctx, const unsigned char key[32])
+{
+    ctx->nonce[0] = U8TOU32(&key[16]);
+    ctx->nonce[1] = U8TOU32(&key[20]);
+    ctx->nonce[2] = U8TOU32(&key[24]);
+    ctx->nonce[3] = U8TOU32(&key[28]);
+
+#ifndef POLY1305_ASM
+    poly1305_init(ctx->opaque, key);
+#else
+    /*
+     * Unlike reference poly1305_init assembly counterpart is expected
+     * to return a value: non-zero if it initializes ctx->func, and zero
+     * otherwise. Latter is to simplify assembly in cases when there no
+     * multiple code paths to switch between.
+     */
+    if (!poly1305_init(ctx->opaque, key, &ctx->func)) {
+        ctx->func.blocks = poly1305_blocks;
+        ctx->func.emit = poly1305_emit;
+    }
+#endif
+
+    ctx->num = 0;
+
+}
+
+void Poly1305_Update(POLY1305 *ctx, const unsigned char *inp, size_t len)
+{
+#ifdef POLY1305_ASM
+    /*
+     * As documented, poly1305_blocks is never called with input
+     * longer than single block and padbit argument set to 0. This
+     * property is fluently used in assembly modules to optimize
+     * padbit handling on loop boundary.
+     */
+    poly1305_blocks_f poly1305_blocks = ctx->func.blocks;
+#endif
+    size_t rem, num;
+
+    if ((num = ctx->num)) {
+        rem = POLY1305_BLOCK_SIZE - num;
+        if (len >= rem) {
+            memcpy(ctx->data + num, inp, rem);
+            poly1305_blocks(ctx->opaque, ctx->data, POLY1305_BLOCK_SIZE, 1);
+            inp += rem;
+            len -= rem;
+        } else {
+            /* Still not enough data to process a block. */
+            memcpy(ctx->data + num, inp, len);
+            ctx->num = num + len;
+            return;
+        }
+    }
+
+    rem = len % POLY1305_BLOCK_SIZE;
+    len -= rem;
+
+    if (len >= POLY1305_BLOCK_SIZE) {
+        poly1305_blocks(ctx->opaque, inp, len, 1);
+        inp += len;
+    }
+
+    if (rem)
+        memcpy(ctx->data, inp, rem);
+
+    ctx->num = rem;
+}
+
+void Poly1305_Final(POLY1305 *ctx, unsigned char mac[16])
+{
+#ifdef POLY1305_ASM
+    poly1305_blocks_f poly1305_blocks = ctx->func.blocks;
+    poly1305_emit_f poly1305_emit = ctx->func.emit;
+#endif
+    size_t num;
+
+    if ((num = ctx->num)) {
+        ctx->data[num++] = 1;   /* pad bit */
+        while (num < POLY1305_BLOCK_SIZE)
+            ctx->data[num++] = 0;
+        poly1305_blocks(ctx->opaque, ctx->data, POLY1305_BLOCK_SIZE, 0);
+    }
+
+    poly1305_emit(ctx->opaque, mac, ctx->nonce);
+
+    /* zero out the state */
+    memset(ctx, 0, sizeof(*ctx));
+}
+
+#ifdef SELFTEST
+#include <stdio.h>
+
+struct poly1305_test {
+    const char *inputhex;
+    const char *keyhex;
+    const char *outhex;
+};
+
+static const struct poly1305_test poly1305_tests[] = {
+    /*
+     * RFC7539
+     */
+    {
+     "43727970746f6772617068696320466f72756d2052657365617263682047726f"
+     "7570",
+     "85d6be7857556d337f4452fe42d506a8""0103808afb0db2fd4abff6af4149f51b",
+     "a8061dc1305136c6c22b8baf0c0127a9"
+    },
+    /*
+     * test vectors from "The Poly1305-AES message-authentication code"
+     */
+    {
+     "f3f6",
+     "851fc40c3467ac0be05cc20404f3f700""580b3b0f9447bb1e69d095b5928b6dbc",
+     "f4c633c3044fc145f84f335cb81953de"
+    },
+    {
+     "",
+     "a0f3080000f46400d0c7e9076c834403""dd3fab2251f11ac759f0887129cc2ee7",
+     "dd3fab2251f11ac759f0887129cc2ee7"
+    },
+    {
+     "663cea190ffb83d89593f3f476b6bc24d7e679107ea26adb8caf6652d0656136",
+     "48443d0bb0d21109c89a100b5ce2c208""83149c69b561dd88298a1798b10716ef",
+     "0ee1c16bb73f0f4fd19881753c01cdbe"
+    },
+    {
+     "ab0812724a7f1e342742cbed374d94d136c6b8795d45b3819830f2c04491faf0"
+     "990c62e48b8018b2c3e4a0fa3134cb67fa83e158c994d961c4cb21095c1bf9",
+     "12976a08c4426d0ce8a82407c4f48207""80f8c20aa71202d1e29179cbcb555a57",
+     "5154ad0d2cb26e01274fc51148491f1b"
+    },
+    /*
+     * self-generated
+     */
+    {
+     "ab0812724a7f1e342742cbed374d94d136c6b8795d45b3819830f2c04491faf0"
+     "990c62e48b8018b2c3e4a0fa3134cb67fa83e158c994d961c4cb21095c1bf9af",
+     "12976a08c4426d0ce8a82407c4f48207""80f8c20aa71202d1e29179cbcb555a57",
+     "812059a5da198637cac7c4a631bee466"
+    },
+    {
+     "ab0812724a7f1e342742cbed374d94d136c6b8795d45b3819830f2c04491faf0"
+     "990c62e48b8018b2c3e4a0fa3134cb67",
+     "12976a08c4426d0ce8a82407c4f48207""80f8c20aa71202d1e29179cbcb555a57",
+     "5b88d7f6228b11e2e28579a5c0c1f761"
+    },
+    {
+     "ab0812724a7f1e342742cbed374d94d136c6b8795d45b3819830f2c04491faf0"
+     "990c62e48b8018b2c3e4a0fa3134cb67fa83e158c994d961c4cb21095c1bf9af"
+     "663cea190ffb83d89593f3f476b6bc24d7e679107ea26adb8caf6652d0656136",
+     "12976a08c4426d0ce8a82407c4f48207""80f8c20aa71202d1e29179cbcb555a57",
+     "bbb613b2b6d753ba07395b916aaece15"
+    },
+    {
+     "ab0812724a7f1e342742cbed374d94d136c6b8795d45b3819830f2c04491faf0"
+     "990c62e48b8018b2c3e4a0fa3134cb67fa83e158c994d961c4cb21095c1bf9af"
+     "48443d0bb0d21109c89a100b5ce2c20883149c69b561dd88298a1798b10716ef"
+     "663cea190ffb83d89593f3f476b6bc24",
+     "12976a08c4426d0ce8a82407c4f48207""80f8c20aa71202d1e29179cbcb555a57",
+     "c794d7057d1778c4bbee0a39b3d97342"
+    },
+    {
+     "ab0812724a7f1e342742cbed374d94d136c6b8795d45b3819830f2c04491faf0"
+     "990c62e48b8018b2c3e4a0fa3134cb67fa83e158c994d961c4cb21095c1bf9af"
+     "48443d0bb0d21109c89a100b5ce2c20883149c69b561dd88298a1798b10716ef"
+     "663cea190ffb83d89593f3f476b6bc24d7e679107ea26adb8caf6652d0656136",
+     "12976a08c4426d0ce8a82407c4f48207""80f8c20aa71202d1e29179cbcb555a57",
+     "ffbcb9b371423152d7fca5ad042fbaa9"
+    },
+    {
+     "ab0812724a7f1e342742cbed374d94d136c6b8795d45b3819830f2c04491faf0"
+     "990c62e48b8018b2c3e4a0fa3134cb67fa83e158c994d961c4cb21095c1bf9af"
+     "48443d0bb0d21109c89a100b5ce2c20883149c69b561dd88298a1798b10716ef"
+     "663cea190ffb83d89593f3f476b6bc24d7e679107ea26adb8caf6652d0656136"
+     "812059a5da198637cac7c4a631bee466",
+     "12976a08c4426d0ce8a82407c4f48207""80f8c20aa71202d1e29179cbcb555a57",
+     "069ed6b8ef0f207b3e243bb1019fe632"
+    },
+    {
+     "ab0812724a7f1e342742cbed374d94d136c6b8795d45b3819830f2c04491faf0"
+     "990c62e48b8018b2c3e4a0fa3134cb67fa83e158c994d961c4cb21095c1bf9af"
+     "48443d0bb0d21109c89a100b5ce2c20883149c69b561dd88298a1798b10716ef"
+     "663cea190ffb83d89593f3f476b6bc24d7e679107ea26adb8caf6652d0656136"
+     "812059a5da198637cac7c4a631bee4665b88d7f6228b11e2e28579a5c0c1f761",
+     "12976a08c4426d0ce8a82407c4f48207""80f8c20aa71202d1e29179cbcb555a57",
+     "cca339d9a45fa2368c2c68b3a4179133"
+    },
+    {
+     "ab0812724a7f1e342742cbed374d94d136c6b8795d45b3819830f2c04491faf0"
+     "990c62e48b8018b2c3e4a0fa3134cb67fa83e158c994d961c4cb21095c1bf9af"
+     "48443d0bb0d21109c89a100b5ce2c20883149c69b561dd88298a1798b10716ef"
+     "663cea190ffb83d89593f3f476b6bc24d7e679107ea26adb8caf6652d0656136"
+     "812059a5da198637cac7c4a631bee4665b88d7f6228b11e2e28579a5c0c1f761"
+     "ab0812724a7f1e342742cbed374d94d136c6b8795d45b3819830f2c04491faf0"
+     "990c62e48b8018b2c3e4a0fa3134cb67fa83e158c994d961c4cb21095c1bf9af"
+     "48443d0bb0d21109c89a100b5ce2c20883149c69b561dd88298a1798b10716ef"
+     "663cea190ffb83d89593f3f476b6bc24d7e679107ea26adb8caf6652d0656136",
+     "12976a08c4426d0ce8a82407c4f48207""80f8c20aa71202d1e29179cbcb555a57",
+     "53f6e828a2f0fe0ee815bf0bd5841a34"
+    },
+    {
+     "ab0812724a7f1e342742cbed374d94d136c6b8795d45b3819830f2c04491faf0"
+     "990c62e48b8018b2c3e4a0fa3134cb67fa83e158c994d961c4cb21095c1bf9af"
+     "48443d0bb0d21109c89a100b5ce2c20883149c69b561dd88298a1798b10716ef"
+     "663cea190ffb83d89593f3f476b6bc24d7e679107ea26adb8caf6652d0656136"
+     "812059a5da198637cac7c4a631bee4665b88d7f6228b11e2e28579a5c0c1f761"
+     "ab0812724a7f1e342742cbed374d94d136c6b8795d45b3819830f2c04491faf0"
+     "990c62e48b8018b2c3e4a0fa3134cb67fa83e158c994d961c4cb21095c1bf9af"
+     "48443d0bb0d21109c89a100b5ce2c20883149c69b561dd88298a1798b10716ef"
+     "663cea190ffb83d89593f3f476b6bc24d7e679107ea26adb8caf6652d0656136"
+     "812059a5da198637cac7c4a631bee4665b88d7f6228b11e2e28579a5c0c1f761",
+     "12976a08c4426d0ce8a82407c4f48207""80f8c20aa71202d1e29179cbcb555a57",
+     "b846d44e9bbd53cedffbfbb6b7fa4933"
+    },
+    {
+    /*
+     * poly1305_ieee754.c failed this in final stage
+     */
+     "842364e156336c0998b933a6237726180d9e3fdcbde4cd5d17080fc3beb49614"
+     "d7122c037463ff104d73f19c12704628d417c4c54a3fe30d3c3d7714382d43b0"
+     "382a50a5dee54be844b076e8df88201a1cd43b90eb21643fa96f39b518aa8340"
+     "c942ff3c31baf7c9bdbf0f31ae3fa096bf8c63030609829fe72e179824890bc8"
+     "e08c315c1cce2a83144dbbff09f74e3efc770b54d0984a8f19b14719e6363564"
+     "1d6b1eedf63efbf080e1783d32445412114c20de0b837a0dfa33d6b82825fff4"
+     "4c9a70ea54ce47f07df698e6b03323b53079364a5fc3e9dd034392bdde86dccd"
+     "da94321c5e44060489336cb65bf3989c36f7282c2f5d2b882c171e74",
+     "95d5c005503e510d8cd0aa072c4a4d06""6eabc52d11653df47fbf63ab198bcc26",
+     "f248312e578d9d58f8b7bb4d19105431"
+    },
+    /*
+     * test vectors from Google
+     */
+    {
+     "",
+     "c8afaac331ee372cd6082de134943b17""4710130e9f6fea8d72293850a667d86c",
+     "4710130e9f6fea8d72293850a667d86c",
+    },
+    {
+     "48656c6c6f20776f726c6421",
+     "746869732069732033322d6279746520""6b657920666f7220506f6c7931333035",
+     "a6f745008f81c916a20dcc74eef2b2f0"
+    },
+    {
+     "0000000000000000000000000000000000000000000000000000000000000000",
+     "746869732069732033322d6279746520""6b657920666f7220506f6c7931333035",
+     "49ec78090e481ec6c26b33b91ccc0307"
+    },
+    /*
+     * test vectors from Andrew Moon
+     */
+    {   /* nacl */
+     "8e993b9f48681273c29650ba32fc76ce48332ea7164d96a4476fb8c531a1186a"
+     "c0dfc17c98dce87b4da7f011ec48c97271d2c20f9b928fe2270d6fb863d51738"
+     "b48eeee314a7cc8ab932164548e526ae90224368517acfeabd6bb3732bc0e9da"
+     "99832b61ca01b6de56244a9e88d5f9b37973f622a43d14a6599b1f654cb45a74"
+     "e355a5",
+     "eea6a7251c1e72916d11c2cb214d3c25""2539121d8e234e652d651fa4c8cff880",
+     "f3ffc7703f9400e52a7dfb4b3d3305d9"
+    },
+    {   /* wrap 2^130-5 */
+     "ffffffffffffffffffffffffffffffff",
+     "02000000000000000000000000000000""00000000000000000000000000000000",
+     "03000000000000000000000000000000"
+    },
+    {   /* wrap 2^128 */
+     "02000000000000000000000000000000",
+     "02000000000000000000000000000000""ffffffffffffffffffffffffffffffff",
+     "03000000000000000000000000000000"
+    },
+    {   /* limb carry */
+     "fffffffffffffffffffffffffffffffff0ffffffffffffffffffffffffffffff"
+     "11000000000000000000000000000000",
+     "01000000000000000000000000000000""00000000000000000000000000000000",
+     "05000000000000000000000000000000"
+    },
+    {   /* 2^130-5 */
+     "fffffffffffffffffffffffffffffffffbfefefefefefefefefefefefefefefe"
+     "01010101010101010101010101010101",
+     "01000000000000000000000000000000""00000000000000000000000000000000",
+     "00000000000000000000000000000000"
+    },
+    {   /* 2^130-6 */
+     "fdffffffffffffffffffffffffffffff",
+     "02000000000000000000000000000000""00000000000000000000000000000000",
+     "faffffffffffffffffffffffffffffff"
+    },
+    {   /* 5*H+L reduction intermediate */
+     "e33594d7505e43b900000000000000003394d7505e4379cd0100000000000000"
+     "0000000000000000000000000000000001000000000000000000000000000000",
+     "01000000000000000400000000000000""00000000000000000000000000000000",
+     "14000000000000005500000000000000"
+    },
+    {   /* 5*H+L reduction final */
+     "e33594d7505e43b900000000000000003394d7505e4379cd0100000000000000"
+     "00000000000000000000000000000000",
+     "01000000000000000400000000000000""00000000000000000000000000000000",
+     "13000000000000000000000000000000"
+    }
+};
+
+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]);
+}
+
+int main()
+{
+    static const unsigned num_tests =
+        sizeof(poly1305_tests) / sizeof(struct poly1305_test);
+    unsigned i;
+    unsigned char key[32], out[16], expected[16];
+    POLY1305 poly1305;
+
+    for (i = 0; i < num_tests; 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);
+
+        Poly1305_Init(&poly1305, key);
+        Poly1305_Update(&poly1305, in, inlen);
+        Poly1305_Final(&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;
+        }
+
+        if (inlen > 16) {
+            Poly1305_Init(&poly1305, key);
+            Poly1305_Update(&poly1305, in, 1);
+            Poly1305_Update(&poly1305, in+1, inlen-1);
+            Poly1305_Final(&poly1305, out);
+
+            if (memcmp(out, expected, sizeof(expected)) != 0) {
+                printf("Poly1305 test #%d/1+(N-1) failed.\n", i);
+                printf("got:      ");
+                hexdump(out, sizeof(out));
+                printf("\nexpected: ");
+                hexdump(expected, sizeof(expected));
+                printf("\n");
+                return 1;
+            }
+        }
+
+        if (inlen > 32) {
+            size_t half = inlen / 2;
+
+            Poly1305_Init(&poly1305, key);
+            Poly1305_Update(&poly1305, in, half);
+            Poly1305_Update(&poly1305, in+half, inlen-half);
+            Poly1305_Final(&poly1305, out);
+
+            if (memcmp(out, expected, sizeof(expected)) != 0) {
+                printf("Poly1305 test #%d/2 failed.\n", i);
+                printf("got:      ");
+                hexdump(out, sizeof(out));
+                printf("\nexpected: ");
+                hexdump(expected, sizeof(expected));
+                printf("\n");
+                return 1;
+            }
+        }
+
+        free(in);
+    }
+
+    printf("PASS\n");
+
+# ifdef OPENSSL_CPUID_OBJ
+    {
+        unsigned char buf[8192];
+        unsigned long long stopwatch;
+        unsigned long long OPENSSL_rdtsc();
+
+        memset (buf,0x55,sizeof(buf));
+        memset (key,0xAA,sizeof(key));
+
+        Poly1305_Init(&poly1305, key);
+
+        for (i=0;i<100000;i++)
+	    Poly1305_Update(&poly1305,buf,sizeof(buf));
+
+	stopwatch = OPENSSL_rdtsc();
+        for (i=0;i<10000;i++)
+	    Poly1305_Update(&poly1305,buf,sizeof(buf));
+	stopwatch = OPENSSL_rdtsc() - stopwatch;
+
+	printf("%g\n",stopwatch/(double)(i*sizeof(buf)));
+
+        stopwatch = OPENSSL_rdtsc();
+        for (i=0;i<10000;i++) {
+            Poly1305_Init(&poly1305, key);
+            Poly1305_Update(&poly1305,buf,16);
+            Poly1305_Final(&poly1305,buf);
+        }
+        stopwatch = OPENSSL_rdtsc() - stopwatch;
+
+        printf("%g\n",stopwatch/(double)(i));
+    }
+# endif
+    return 0;
+}
+#endif
diff --git a/include/openssl/evp.h b/include/openssl/evp.h
index bc9fc8b..969a0fa 100644
--- a/include/openssl/evp.h
+++ b/include/openssl/evp.h
@@ -911,6 +911,12 @@ const EVP_CIPHER *EVP_camellia_256_cfb128(void);
 const EVP_CIPHER *EVP_camellia_256_ofb(void);
 const EVP_CIPHER *EVP_camellia_256_ctr(void);
 # endif
+# ifndef OPENSSL_NO_CHACHA
+const EVP_CIPHER *EVP_chacha20(void);
+#  ifndef OPENSSL_NO_POLY1305
+const EVP_CIPHER *EVP_chacha20_poly1305(void);
+#  endif
+# endif
 
 # ifndef OPENSSL_NO_SEED
 const EVP_CIPHER *EVP_seed_ecb(void);
@@ -1513,6 +1519,7 @@ void ERR_load_EVP_strings(void);
 # define EVP_F_AES_XTS_CIPHER                             175
 # define EVP_F_ALG_MODULE_INIT                            177
 # define EVP_F_CAMELLIA_INIT_KEY                          159
+# define EVP_F_CHACHA20_POLY1305_CTRL                     182
 # define EVP_F_CMAC_INIT                                  173
 # define EVP_F_CMLL_T4_INIT_KEY                           179
 # define EVP_F_D2I_PKEY                                   100
@@ -1600,6 +1607,7 @@ void ERR_load_EVP_strings(void);
 # define EVP_R_CAMELLIA_KEY_SETUP_FAILED                  157
 # define EVP_R_CIPHER_PARAMETER_ERROR                     122
 # define EVP_R_COMMAND_NOT_SUPPORTED                      147
+# define EVP_R_COPY_ERROR                                 173
 # define EVP_R_CTRL_NOT_IMPLEMENTED                       132
 # define EVP_R_CTRL_OPERATION_NOT_IMPLEMENTED             133
 # define EVP_R_DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH          138
diff --git a/include/openssl/obj_mac.h b/include/openssl/obj_mac.h
index 4388f70..060126b 100644
--- a/include/openssl/obj_mac.h
+++ b/include/openssl/obj_mac.h
@@ -4301,6 +4301,14 @@
 #define LN_aes_256_cbc_hmac_sha256              "aes-256-cbc-hmac-sha256"
 #define NID_aes_256_cbc_hmac_sha256             950
 
+#define SN_chacha20_poly1305            "ChaCha20-Poly1305"
+#define LN_chacha20_poly1305            "chacha20-poly1305"
+#define NID_chacha20_poly1305           1018
+
+#define SN_chacha20             "ChaCha20"
+#define LN_chacha20             "chacha20"
+#define NID_chacha20            1019
+
 #define SN_dhpublicnumber               "dhpublicnumber"
 #define LN_dhpublicnumber               "X9.42 DH"
 #define NID_dhpublicnumber              920
diff --git a/include/openssl/ssl.h b/include/openssl/ssl.h
index bc58b0b..81a3ed7 100644
--- a/include/openssl/ssl.h
+++ b/include/openssl/ssl.h
@@ -249,6 +249,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_GOST            "GOST89"
 
 # define SSL_TXT_MD5             "MD5"
diff --git a/include/openssl/tls1.h b/include/openssl/tls1.h
index 3bbd1f1..43a658d 100644
--- a/include/openssl/tls1.h
+++ b/include/openssl/tls1.h
@@ -652,6 +652,15 @@ SSL_CTX_callback_ctrl(ssl,SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB,(void (*)(void))cb)
 # define TLS1_CK_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256   0x0300C09A
 # define TLS1_CK_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384   0x0300C09B
 
+/* draft-ietf-tls-chacha20-poly1305-03 */
+# define TLS1_CK_ECDHE_RSA_WITH_CHACHA20_POLY1305         0x0300CCA8
+# define TLS1_CK_ECDHE_ECDSA_WITH_CHACHA20_POLY1305       0x0300CCA9
+# define TLS1_CK_DHE_RSA_WITH_CHACHA20_POLY1305           0x0300CCAA
+# define TLS1_CK_PSK_WITH_CHACHA20_POLY1305               0x0300CCAB
+# define TLS1_CK_ECDHE_PSK_WITH_CHACHA20_POLY1305         0x0300CCAC
+# define TLS1_CK_DHE_PSK_WITH_CHACHA20_POLY1305           0x0300CCAD
+# define TLS1_CK_RSA_PSK_WITH_CHACHA20_POLY1305           0x0300CCAE
+
 /*
  * XXX Backward compatibility alert: Older versions of OpenSSL gave some DHE
  * ciphers names with "EDH" instead of "DHE".  Going forward, we should be
@@ -912,6 +921,15 @@ SSL_CTX_callback_ctrl(ssl,SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB,(void (*)(void))cb)
 # define TLS1_TXT_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256    "ECDH-RSA-CAMELLIA128-SHA256"
 # define TLS1_TXT_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384    "ECDH-RSA-CAMELLIA256-SHA384"
 
+/* draft-ietf-tls-chacha20-poly1305-03 */
+# 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 TLS1_TXT_PSK_WITH_CHACHA20_POLY1305               "PSK-CHACHA20-POLY1305"
+# define TLS1_TXT_ECDHE_PSK_WITH_CHACHA20_POLY1305         "ECDHE-PSK-CHACHA20-POLY1305"
+# define TLS1_TXT_DHE_PSK_WITH_CHACHA20_POLY1305           "DHE-PSK-CHACHA20-POLY1305"
+# define TLS1_TXT_RSA_PSK_WITH_CHACHA20_POLY1305           "RSA-PSK-CHACHA20-POLY1305"
+
 # define TLS_CT_RSA_SIGN                 1
 # define TLS_CT_DSS_SIGN                 2
 # define TLS_CT_RSA_FIXED_DH             3
diff --git a/ssl/s3_lib.c b/ssl/s3_lib.c
index 03d0320..b6a73b9 100644
--- a/ssl/s3_lib.c
+++ b/ssl/s3_lib.c
@@ -3527,6 +3527,119 @@ OPENSSL_GLOBAL const SSL_CIPHER ssl3_ciphers[] = {
      256,
      256,
      },
+#if !defined(OPENSSL_NO_CHACHA) && !defined(OPENSSL_NO_POLY1305)
+# ifndef OPENSSL_NO_EC
+    /* Cipher CCA8 as per draft-ietf-tls-chacha20-poly1305-03 */
+    {
+     1,
+     TLS1_TXT_ECDHE_RSA_WITH_CHACHA20_POLY1305,
+     TLS1_CK_ECDHE_RSA_WITH_CHACHA20_POLY1305,
+     SSL_kECDHE,
+     SSL_aRSA,
+     SSL_CHACHA20POLY1305,
+     SSL_AEAD,
+     SSL_TLSV1_2,
+     SSL_HIGH,
+     SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256,
+     256,
+     256,
+     },
+    /* Cipher CCA9 */
+    {
+     1,
+     TLS1_TXT_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,
+     TLS1_CK_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,
+     SSL_kECDHE,
+     SSL_aECDSA,
+     SSL_CHACHA20POLY1305,
+     SSL_AEAD,
+     SSL_TLSV1_2,
+     SSL_HIGH,
+     SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256,
+     256,
+     256,
+     },
+# endif
+# ifndef OPENSSL_NO_RSA
+    /* Cipher CCAA */
+    {
+     1,
+     TLS1_TXT_DHE_RSA_WITH_CHACHA20_POLY1305,
+     TLS1_CK_DHE_RSA_WITH_CHACHA20_POLY1305,
+     SSL_kDHE,
+     SSL_aRSA,
+     SSL_CHACHA20POLY1305,
+     SSL_AEAD,
+     SSL_TLSV1_2,
+     SSL_HIGH,
+     SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256,
+     256,
+     256,
+     },
+# endif
+# ifndef OPENSSL_NO_PSK
+    /* Cipher CCAB */
+    {
+     1,
+     TLS1_TXT_PSK_WITH_CHACHA20_POLY1305,
+     TLS1_CK_PSK_WITH_CHACHA20_POLY1305,
+     SSL_kPSK,
+     SSL_aPSK,
+     SSL_CHACHA20POLY1305,
+     SSL_AEAD,
+     SSL_TLSV1_2,
+     SSL_HIGH,
+     SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256,
+     256,
+     256,
+     },
+    /* Cipher CCAC */
+    {
+     1,
+     TLS1_TXT_ECDHE_PSK_WITH_CHACHA20_POLY1305,
+     TLS1_CK_ECDHE_PSK_WITH_CHACHA20_POLY1305,
+     SSL_kECDHEPSK,
+     SSL_aPSK,
+     SSL_CHACHA20POLY1305,
+     SSL_AEAD,
+     SSL_TLSV1_2,
+     SSL_HIGH,
+     SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256,
+     256,
+     256,
+     },
+    /* Cipher CCAD */
+    {
+     1,
+     TLS1_TXT_DHE_PSK_WITH_CHACHA20_POLY1305,
+     TLS1_CK_DHE_PSK_WITH_CHACHA20_POLY1305,
+     SSL_kDHEPSK,
+     SSL_aPSK,
+     SSL_CHACHA20POLY1305,
+     SSL_AEAD,
+     SSL_TLSV1_2,
+     SSL_HIGH,
+     SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256,
+     256,
+     256,
+     },
+    /* Cipher CCAE */
+    {
+     1,
+     TLS1_TXT_RSA_PSK_WITH_CHACHA20_POLY1305,
+     TLS1_CK_RSA_PSK_WITH_CHACHA20_POLY1305,
+     SSL_kRSAPSK,
+     SSL_aRSA,
+     SSL_CHACHA20POLY1305,
+     SSL_AEAD,
+     SSL_TLSV1_2,
+     SSL_HIGH,
+     SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256,
+     256,
+     256,
+     },
+# endif
+#endif
 #ifndef OPENSSL_NO_GOST
     {
      1,
diff --git a/ssl/ssl_algs.c b/ssl/ssl_algs.c
index 9a7f155..fc6af90 100644
--- a/ssl/ssl_algs.c
+++ b/ssl/ssl_algs.c
@@ -102,6 +102,9 @@ int SSL_library_init(void)
     EVP_add_cipher(EVP_camellia_128_cbc());
     EVP_add_cipher(EVP_camellia_256_cbc());
 #endif
+#if !defined(OPENSSL_NO_CHACHA) && !defined(OPENSSL_NO_POLY1305)
+    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 69a0cc8..ea6aba0 100644
--- a/ssl/ssl_ciph.c
+++ b/ssl/ssl_ciph.c
@@ -169,7 +169,8 @@
 #define SSL_ENC_AES128CCM8_IDX  16
 #define SSL_ENC_AES256CCM8_IDX  17
 #define SSL_ENC_GOST8912_IDX    18
-#define SSL_ENC_NUM_IDX         19
+#define SSL_ENC_CHACHA_IDX      19
+#define SSL_ENC_NUM_IDX         20
 
 /* NB: make sure indices in these tables match values above */
 
@@ -199,6 +200,7 @@ static const ssl_cipher_table ssl_cipher_table_cipher[SSL_ENC_NUM_IDX] = {
     {SSL_AES128CCM8, NID_aes_128_ccm}, /* SSL_ENC_AES128CCM8_IDX 16 */
     {SSL_AES256CCM8, NID_aes_256_ccm}, /* SSL_ENC_AES256CCM8_IDX 17 */
     {SSL_eGOST2814789CNT12, NID_gost89_cnt_12}, /* SSL_ENC_GOST8912_IDX */
+    {SSL_CHACHA20POLY1305, NID_chacha20_poly1305},
 };
 
 static const EVP_CIPHER *ssl_cipher_methods[SSL_ENC_NUM_IDX] = {
diff --git a/ssl/ssl_locl.h b/ssl/ssl_locl.h
index 1e1b265..b161387 100644
--- a/ssl/ssl_locl.h
+++ b/ssl/ssl_locl.h
@@ -368,6 +368,7 @@
 # define SSL_AES128CCM8          0x00010000U
 # define SSL_AES256CCM8          0x00020000U
 # define SSL_eGOST2814789CNT12   0x00040000U
+# define SSL_CHACHA20POLY1305    0x00080000U
 
 # define SSL_AES                 (SSL_AES128|SSL_AES256|SSL_AES128GCM|SSL_AES256GCM|SSL_AES128CCM|SSL_AES256CCM|SSL_AES128CCM8|SSL_AES256CCM8)
 # define SSL_CAMELLIA            (SSL_CAMELLIA128|SSL_CAMELLIA256)
diff --git a/ssl/t1_trce.c b/ssl/t1_trce.c
index 3a4f039..6f5bed7 100644
--- a/ssl/t1_trce.c
+++ b/ssl/t1_trce.c
@@ -461,6 +461,13 @@ static ssl_trace_tbl ssl_ciphers_tbl[] = {
     {0xC0AD, "TLS_ECDHE_ECDSA_WITH_AES_256_CCM"},
     {0xC0AE, "TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8"},
     {0xC0AF, "TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8"},
+    {0xCCA8, "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305" },
+    {0xCCA9, "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305" },
+    {0xCCAA, "TLS_DHE_RSA_WITH_CHACHA20_POLY1305" },
+    {0xCCAB, "TLS_PSK_WITH_CHACHA20_POLY1305" },
+    {0xCCAC, "TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305" },
+    {0xCCAD, "TLS_DHE_PSK_WITH_CHACHA20_POLY1305" },
+    {0xCCAE, "TLS_RSA_PSK_WITH_CHACHA20_POLY1305" },
     {0xFEFE, "SSL_RSA_FIPS_WITH_DES_CBC_SHA"},
     {0xFEFF, "SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA"},
 };
diff --git a/test/evp_test.c b/test/evp_test.c
index 725af8a..ec2283a 100644
--- a/test/evp_test.c
+++ b/test/evp_test.c
@@ -774,6 +774,8 @@ static int cipher_test_init(struct evp_test *t, const char *alg)
         || EVP_CIPHER_mode(cipher) == EVP_CIPH_OCB_MODE
         || EVP_CIPHER_mode(cipher) == EVP_CIPH_CCM_MODE)
         cdat->aead = EVP_CIPHER_mode(cipher);
+    else if (EVP_CIPHER_flags(cipher) & EVP_CIPH_FLAG_AEAD_CIPHER)
+        cdat->aead = -1;
     else
         cdat->aead = 0;
 
diff --git a/test/evptests.txt b/test/evptests.txt
index 24ef573..8bdca59 100644
--- a/test/evptests.txt
+++ b/test/evptests.txt
@@ -2803,3 +2803,68 @@ Output = "T3BlblNTTE9wZW5TU0wK\n-abcd"
 Encoding = valid
 Input = "OpenSSLOpenSSL\n"
 Output = "T3BlblNTTE9wZW5TU0wK-abcd"
+
+Cipher = chacha20
+Key = 0000000000000000000000000000000000000000000000000000000000000000
+IV = 00000000000000000000000000000000
+Plaintext = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+Ciphertext = 76b8e0ada0f13d90405d6ae55386bd28bdd219b8a08ded1aa836efcc8b770dc7da41597c5157488d7724e03fb8d84a376a43b8f41518a11cc387b669b2ee6586
+
+Cipher = chacha20
+Key = 0000000000000000000000000000000000000000000000000000000000000001
+IV = 00000000000000000000000000000000
+Plaintext = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+Ciphertext = 4540f05a9f1fb296d7736e7b208e3c96eb4fe1834688d2604f450952ed432d41bbe2a0b6ea7566d2a5d1e7e20d42af2c53d792b1c43fea817e9ad275ae546963
+
+Cipher = chacha20
+Key = 0000000000000000000000000000000000000000000000000000000000000000
+IV = 00000000000000000000000000000001
+Plaintext = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+Ciphertext = de9cba7bf3d69ef5e786dc63973f653a0b49e015adbff7134fcb7df137821031e85a050278a7084527214f73efc7fa5b5277062eb7a0433e445f41e31afab757
+
+Cipher = chacha20
+Key = 0000000000000000000000000000000000000000000000000000000000000000
+IV = 00000000000000000100000000000000
+Plaintext = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+Ciphertext = ef3fdfd6c61578fbf5cf35bd3dd33b8009631634d21e42ac33960bd138e50d32111e4caf237ee53ca8ad6426194a88545ddc497a0b466e7d6bbdb0041b2f586b
+
+Cipher = chacha20
+Key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
+IV = 00000000000000000001020304050607
+Plaintext = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+Ciphertext = f798a189f195e66982105ffb640bb7757f579da31602fc93ec01ac56f85ac3c134a4547b733b46413042c9440049176905d3be59ea1c53f15916155c2be8241a38008b9a26bc35941e2444177c8ade6689de95264986d95889fb60e84629c9bd9a5acb1cc118be563eb9b3a4a472f82e09a7e778492b562ef7130e88dfe031c79db9d4f7c7a899151b9a475032b63fc385245fe054e3dd5a97a5f576fe064025d3ce042c566ab2c507b138db853e3d6959660996546cc9c4a6eafdc777c040d70eaf46f76dad3979e5c5360c3317166a1c894c94a371876a94df7628fe4eaaf2ccb27d5aaae0ad7ad0f9d4b6ad3b54098746d4524d38407a6deb
+
+Cipher = chacha20
+Key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
+IV = 00000000000000000001020304050607
+Plaintext = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+Ciphertext = f798a189f195e66982105ffb640bb7757f579da31602fc93ec01ac56f85ac3c134a4547b733b46413042c9440049176905d3be59ea1c53f15916155c2be8241a38008b9a26bc35941e2444177c8ade6689de95264986d95889fb60e84629c9bd9a5acb1cc118be563eb9b3a4a472f82e09a7e778492b562ef7130e88dfe031c79db9d4f7c7a899151b9a475032b63fc385245fe054e3dd5a97a5f576fe064025d3ce042c566ab2c507b138db853e3d6959660996546cc9c4a6eafdc777c040d70eaf46f76dad3979e5c5360c3317166a1c894c94a371876a94df7628fe4eaaf2ccb27d5aaae0ad7ad0f9d4b6ad3b54098746d4524d38407a6deb3ab78fab78c9
+
+Cipher = chacha20
+Key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
+IV = 00000000000000000001020304050607
+Plaintext = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+Ciphertext = f798a189f195e66982105ffb640bb7757f579da31602fc93ec01ac56f85ac3c134a4547b733b46413042c9440049176905d3be59ea1c53f15916155c2be8241a38008b9a26bc35941e2444177c8ade6689de95264986d95889fb60e84629c9bd9a5acb1cc118be563eb9b3a4a472f82e09a7e778492b562ef7130e88dfe031c79db9d4f7c7a899151b9a475032b63fc385245fe054e3dd5a97a5f576fe064025d3ce042c566ab2c507b138db853e3d6959660996546cc9c4a6eafdc777c040d70eaf46f76dad3979e5c5360c3317166a1c894c94a371876a94df7628fe4eaaf2ccb27d5aaae0ad7ad0f9d4b6ad3b54098746d4524d38407a6deb3ab78fab78c94213668bbbd394c5de93b853178addd6b97f9fa1ec3e56c00c9ddff0a44a204241175a4cab0f961ba53ede9bdf960b94f9829b1f3414726429b362c5b538e391520f489b7ed8d20ae3fd49e9e259e44397514d618c96c4846be3c680bdc11c71dcbbe29ccf80d62a0938fa549391e6ea57ecbe2606790ec15d2224ae307c144226b7c4e8c2f97d2a1d67852d29beba110edd445197012062a393a9c92803ad3b4f31d7bc6033ccf7932cfed3f019044d25905916777286f82f9a4cc1ffe430ffd1dcfc27deed327b9f9630d2fa969fb6f0603cd19dd9a9519e673bcfcd9014125291a44669ef7285e74ed3729b677f801c3cdf058c50963168b496043716c730
+
+Cipher = chacha20
+Key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
+IV = 00000000000000000001020304050607
+Plaintext = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+Ciphertext = f798a189f195e66982105ffb640bb7757f579da31602fc93ec01ac56f85ac3c134a4547b733b46413042c9440049176905d3be59ea1c53f15916155c2be8241a38008b9a26bc35941e2444177c8ade6689de95264986d95889fb60e84629c9bd9a5acb1cc118be563eb9b3a4a472f82e09a7e778492b562ef7130e88dfe031c79db9d4f7c7a899151b9a475032b63fc385245fe054e3dd5a97a5f576fe064025d3ce042c566ab2c507b138db853e3d6959660996546cc9c4a6eafdc777c040d70eaf46f76dad3979e5c5360c3317166a1c894c94a371876a94df7628fe4eaaf2ccb27d5aaae0ad7ad0f9d4b6ad3b54098746d4524d38407a6deb3ab78fab78c94213668bbbd394c5de93b853178addd6b97f9fa1ec3e56c00c9ddff0a44a204241175a4cab0f961ba53ede9bdf960b94f9829b1f3414726429b362c5b538e391520f489b7ed8d20ae3fd49e9e259e44397514d618c96c4846be3c680bdc11c71dcbbe29ccf80d62a0938fa549391e6ea57ecbe2606790ec15d2224ae307c144226b7c4e8c2f97d2a1d67852d29beba110edd445197012062a393a9c92803ad3b4f31d7bc6033ccf7932cfed3f019044d25905916777286f82f9a4cc1ffe430ffd1dcfc27deed327b9f9630d2fa969fb6f0603cd19dd9a9519e673bcfcd9014125291a44669ef7285e74ed3729b677f801c3cdf058c50963168b496043716c7307cd9e0cdd137fccb0f05b47cdbb95c5f54831622c3652a32b2531fe326bcd6e2bbf56a194fa196fbd1a54952110f51c73433865f7664b836685e3664b3d8444a
+
+# RFC7539
+Cipher = chacha20-poly1305
+Key = 808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f
+IV = 070000004041424344454647
+AAD = 50515253c0c1c2c3c4c5c6c7
+Tag = 1ae10b594f09e26a7e902ecbd0600691
+Plaintext = 4c616469657320616e642047656e746c656d656e206f662074686520636c617373206f66202739393a204966204920636f756c64206f6666657220796f75206f6e6c79206f6e652074697020666f7220746865206675747572652c2073756e73637265656e20776f756c642062652069742e
+Ciphertext = d31a8d34648e60db7b86afbc53ef7ec2a4aded51296e08fea9e2b5a736ee62d63dbea45e8ca9671282fafb69da92728b1a71de0a9e060b2905d6a5b67ecd3b3692ddbd7f2d778b8c9803aee328091b58fab324e4fad675945585808b4831d7bc3ff4def08e4b7a9de576d26586cec64b6116
+
+Cipher = chacha20-poly1305
+Key = 1c9240a5eb55d38af333888604f6b5f0473917c1402b80099dca5cbc207075c0
+IV = 000000000102030405060708
+AAD = f33388860000000000004e91
+Tag = eead9d67890cbb22392336fea1851f38
+Plaintext = 496e7465726e65742d4472616674732061726520647261667420646f63756d656e74732076616c696420666f722061206d6178696d756d206f6620736978206d6f6e74687320616e64206d617920626520757064617465642c207265706c616365642c206f72206f62736f6c65746564206279206f7468657220646f63756d656e747320617420616e792074696d652e20497420697320696e617070726f70726961746520746f2075736520496e7465726e65742d447261667473206173207265666572656e6365206d6174657269616c206f7220746f2063697465207468656d206f74686572207468616e206173202fe2809c776f726b20696e2070726f67726573732e2fe2809d
+Ciphertext = 64a0861575861af460f062c79be643bd5e805cfd345cf389f108670ac76c8cb24c6cfc18755d43eea09ee94e382d26b0bdb7b73c321b0100d4f03b7f355894cf332f830e710b97ce98c8a84abd0b948114ad176e008d33bd60f982b1ff37c8559797a06ef4f0ef61c186324e2b3506383606907b6a7c02b0f9f6157b53c867e4b9166c767b804d46a59b5216cde7a4e99040c5a40433225ee282a1b0a06c523eaf4534d7f83fa1155b0047718cbc546a0d072b04b3564eea1b422273f548271a0bb2316053fa76991955ebd63159434ecebb4e466dae5a1073a6727627097a1049e617d91d361094fa68f0ff77987130305beaba2eda04df997b714d6c6f2c29a6ad5cb4022b02709b
diff --git a/util/libeay.num b/util/libeay.num
index cd13ea0..3318a7e 100755
--- a/util/libeay.num
+++ b/util/libeay.num
@@ -4720,3 +4720,10 @@ EC_KEY_METHOD_get_verify                5079	EXIST::FUNCTION:EC
 ENGINE_unregister_EC                    5080	EXIST::FUNCTION:ENGINE
 EC_KEY_METHOD_get_sign                  5081	EXIST::FUNCTION:EC
 EC_KEY_METHOD_get_compute_key           5082	EXIST::FUNCTION:EC
+Poly1305_Init                           5083	EXIST::FUNCTION:POLY1305
+ChaCha20_ctr32                          5084	EXIST::FUNCTION:CHACHA
+Poly1305_ctx_size                       5085	EXIST::FUNCTION:POLY1305
+Poly1305_Update                         5086	EXIST::FUNCTION:POLY1305
+Poly1305_Final                          5087	EXIST::FUNCTION:POLY1305
+EVP_chacha20_poly1305                   5088	EXIST::FUNCTION:CHACHA,POLY1305
+EVP_chacha20                            5089	EXIST::FUNCTION:CHACHA
diff --git a/util/mkdef.pl b/util/mkdef.pl
index 6a8a096..a57f403 100755
--- a/util/mkdef.pl
+++ b/util/mkdef.pl
@@ -69,7 +69,7 @@ my @known_algorithms = ( "RC2", "RC4", "RC5", "IDEA", "DES", "BF",
 			 "SHA256", "SHA512", "RMD160",
 			 "MDC2", "WHIRLPOOL", "RSA", "DSA", "DH", "EC", "EC2M",
 			 "HMAC", "AES", "CAMELLIA", "SEED", "GOST",
-                         "SCRYPT",
+                         "SCRYPT", "CHACHA", "POLY1305",
 			 # EC_NISTP_64_GCC_128
 			 "EC_NISTP_64_GCC_128",
 			 # Envelope "algorithms"
@@ -128,6 +128,7 @@ my $no_cast; my $no_whirlpool; my $no_camellia; my $no_seed;
 my $no_md2; my $no_md4; my $no_md5; my $no_sha; my $no_ripemd; my $no_mdc2;
 my $no_rsa; my $no_dsa; my $no_dh; my $no_aes; my $no_scrypt;
 my $no_ec; my $no_engine; my $no_hw;
+my $no_chacha; my $no_poly1305;
 my $no_fp_api; my $no_static_engine=1; my $no_gmp; my $no_deprecated;
 my $no_sct; my $no_rfc3779; my $no_psk; my $no_cms; my $no_capieng;
 my $no_jpake; my $no_srp; my $no_ec2m; my $no_nistp_gcc; 
@@ -205,6 +206,8 @@ foreach (@ARGV, split(/ /, $options))
 	elsif (/^no-camellia$/)	{ $no_camellia=1; }
 	elsif (/^no-seed$/)     { $no_seed=1; }
 	elsif (/^no-scrypt$/)   { $no_scrypt=1; }
+	elsif (/^no-chacha$/)   { $no_chacha=1; }
+	elsif (/^no-poly1305$/) { $no_poly1305=1; }
 	elsif (/^no-evp$/)	{ $no_evp=1; }
 	elsif (/^no-lhash$/)	{ $no_lhash=1; }
 	elsif (/^no-stack$/)	{ $no_stack=1; }
@@ -267,6 +270,8 @@ $ssl.=" include/openssl/srtp.h";
 
 my $crypto ="include/openssl/crypto.h";
 $crypto.=" crypto/include/internal/cryptlib.h";
+$crypto.=" crypto/include/internal/chacha.h"; # unless $no_chacha;
+$crypto.=" crypto/include/internal/poly1305.h"; # unless $no_poly1305;
 $crypto.=" include/internal/o_dir.h";
 $crypto.=" include/internal/o_str.h";
 $crypto.=" include/openssl/des.h" ; # unless $no_des;
@@ -1188,6 +1193,8 @@ sub is_valid
 			if ($keyword eq "CAMELLIA" && $no_camellia) { return 0; }
 			if ($keyword eq "SEED" && $no_seed) { return 0; }
 			if ($keyword eq "SCRYPT" && $no_scrypt) { return 0; }
+			if ($keyword eq "CHACHA" && $no_chacha) { return 0; }
+			if ($keyword eq "POLY1305" && $no_poly1305) { return 0; }
 			if ($keyword eq "EVP" && $no_evp) { return 0; }
 			if ($keyword eq "LHASH" && $no_lhash) { return 0; }
 			if ($keyword eq "STACK" && $no_stack) { return 0; }


More information about the openssl-commits mailing list