summaryrefslogtreecommitdiff
path: root/src/lib
diff options
context:
space:
mode:
authorreyk <>2015-11-02 15:40:53 +0000
committerreyk <>2015-11-02 15:40:53 +0000
commitb743c75edf0dc70962a2ed0c5221ecb8841d7525 (patch)
tree40446be7b959dce9252457817e67737c7606706c /src/lib
parent3b76990c68663b08d77297a05a8104c2f1528064 (diff)
downloadopenbsd-b743c75edf0dc70962a2ed0c5221ecb8841d7525.tar.gz
openbsd-b743c75edf0dc70962a2ed0c5221ecb8841d7525.tar.bz2
openbsd-b743c75edf0dc70962a2ed0c5221ecb8841d7525.zip
Add EVP_aead_chacha20_poly1305_ietf() - The informational RFC 7539,
"ChaCha20 and Poly1305 for IETF Protocols", introduced a modified AEAD construction that is incompatible with the common style that has been already used in TLS with EVP_aead_chacha20_poly1305(). The IETF version also adds a constant (salt) that is prepended to the nonce. OK mikeb@ jsing@
Diffstat (limited to 'src/lib')
-rw-r--r--src/lib/libcrypto/evp/e_chacha20poly1305.c129
-rw-r--r--src/lib/libcrypto/evp/evp.h3
-rw-r--r--src/lib/libcrypto/man/EVP_AEAD_CTX_init.333
-rw-r--r--src/lib/libssl/src/crypto/evp/e_chacha20poly1305.c129
-rw-r--r--src/lib/libssl/src/crypto/evp/evp.h3
5 files changed, 256 insertions, 41 deletions
diff --git a/src/lib/libcrypto/evp/e_chacha20poly1305.c b/src/lib/libcrypto/evp/e_chacha20poly1305.c
index 9deb40b72a..47551c4578 100644
--- a/src/lib/libcrypto/evp/e_chacha20poly1305.c
+++ b/src/lib/libcrypto/evp/e_chacha20poly1305.c
@@ -1,5 +1,7 @@
1/* $OpenBSD: e_chacha20poly1305.c,v 1.10 2015/09/10 15:56:25 jsing Exp $ */ 1/* $OpenBSD: e_chacha20poly1305.c,v 1.11 2015/11/02 15:40:53 reyk Exp $ */
2
2/* 3/*
4 * Copyright (c) 2015 Reyk Floter <reyk@openbsd.org>
3 * Copyright (c) 2014, Google Inc. 5 * Copyright (c) 2014, Google Inc.
4 * 6 *
5 * Permission to use, copy, modify, and/or distribute this software for any 7 * Permission to use, copy, modify, and/or distribute this software for any
@@ -32,6 +34,16 @@
32#define POLY1305_TAG_LEN 16 34#define POLY1305_TAG_LEN 16
33#define CHACHA20_NONCE_LEN 8 35#define CHACHA20_NONCE_LEN 8
34 36
37/*
38 * The informational RFC 7539, "ChaCha20 and Poly1305 for IETF Protocols",
39 * introduced a modified AEAD construction that is incompatible with the
40 * common style that that has been already used in TLS. The IETF version
41 * also adds a constant (salt) that is prepended to the nonce.
42 */
43#define CHACHA20_CONSTANT_LEN 4
44#define CHACHA20_IV_LEN 8
45#define CHACHA20_NONCE_LEN_IETF (CHACHA20_CONSTANT_LEN + CHACHA20_IV_LEN)
46
35struct aead_chacha20_poly1305_ctx { 47struct aead_chacha20_poly1305_ctx {
36 unsigned char key[32]; 48 unsigned char key[32];
37 unsigned char tag_len; 49 unsigned char tag_len;
@@ -88,10 +100,27 @@ poly1305_update_with_length(poly1305_state *poly1305,
88 j >>= 8; 100 j >>= 8;
89 } 101 }
90 102
91 CRYPTO_poly1305_update(poly1305, data, data_len); 103 if (data != NULL)
104 CRYPTO_poly1305_update(poly1305, data, data_len);
92 CRYPTO_poly1305_update(poly1305, length_bytes, sizeof(length_bytes)); 105 CRYPTO_poly1305_update(poly1305, length_bytes, sizeof(length_bytes));
93} 106}
94 107
108static void
109poly1305_update_with_pad16(poly1305_state *poly1305,
110 const unsigned char *data, size_t data_len)
111{
112 static const unsigned char zero_pad16[16];
113 size_t pad_len;
114
115 CRYPTO_poly1305_update(poly1305, data, data_len);
116
117 /* pad16() is defined in RFC 7539 2.8.1. */
118 if ((pad_len = data_len % 16) == 0)
119 return;
120
121 CRYPTO_poly1305_update(poly1305, zero_pad16, 16 - pad_len);
122}
123
95static int 124static int
96aead_chacha20_poly1305_seal(const EVP_AEAD_CTX *ctx, unsigned char *out, 125aead_chacha20_poly1305_seal(const EVP_AEAD_CTX *ctx, unsigned char *out,
97 size_t *out_len, size_t max_out_len, const unsigned char *nonce, 126 size_t *out_len, size_t max_out_len, const unsigned char *nonce,
@@ -101,7 +130,9 @@ aead_chacha20_poly1305_seal(const EVP_AEAD_CTX *ctx, unsigned char *out,
101 const struct aead_chacha20_poly1305_ctx *c20_ctx = ctx->aead_state; 130 const struct aead_chacha20_poly1305_ctx *c20_ctx = ctx->aead_state;
102 unsigned char poly1305_key[32]; 131 unsigned char poly1305_key[32];
103 poly1305_state poly1305; 132 poly1305_state poly1305;
133 const unsigned char *iv;
104 const uint64_t in_len_64 = in_len; 134 const uint64_t in_len_64 = in_len;
135 uint64_t ctr;
105 136
106 /* The underlying ChaCha implementation may not overflow the block 137 /* The underlying ChaCha implementation may not overflow the block
107 * counter into the second counter word. Therefore we disallow 138 * counter into the second counter word. Therefore we disallow
@@ -121,19 +152,40 @@ aead_chacha20_poly1305_seal(const EVP_AEAD_CTX *ctx, unsigned char *out,
121 return 0; 152 return 0;
122 } 153 }
123 154
124 if (nonce_len != CHACHA20_NONCE_LEN) { 155 if (nonce_len != ctx->aead->nonce_len) {
125 EVPerr(EVP_F_AEAD_CHACHA20_POLY1305_SEAL, EVP_R_IV_TOO_LARGE); 156 EVPerr(EVP_F_AEAD_CHACHA20_POLY1305_SEAL, EVP_R_IV_TOO_LARGE);
126 return 0; 157 return 0;
127 } 158 }
128 159
129 memset(poly1305_key, 0, sizeof(poly1305_key)); 160 if (nonce_len == CHACHA20_NONCE_LEN) {
130 CRYPTO_chacha_20(poly1305_key, poly1305_key, sizeof(poly1305_key), 161 /* Google's draft-agl-tls-chacha20poly1305-04, Nov 2013 */
131 c20_ctx->key, nonce, 0); 162
132 163 memset(poly1305_key, 0, sizeof(poly1305_key));
133 CRYPTO_poly1305_init(&poly1305, poly1305_key); 164 CRYPTO_chacha_20(poly1305_key, poly1305_key,
134 poly1305_update_with_length(&poly1305, ad, ad_len); 165 sizeof(poly1305_key), c20_ctx->key, nonce, 0);
135 CRYPTO_chacha_20(out, in, in_len, c20_ctx->key, nonce, 1); 166
136 poly1305_update_with_length(&poly1305, out, in_len); 167 CRYPTO_poly1305_init(&poly1305, poly1305_key);
168 poly1305_update_with_length(&poly1305, ad, ad_len);
169 CRYPTO_chacha_20(out, in, in_len, c20_ctx->key, nonce, 1);
170 poly1305_update_with_length(&poly1305, out, in_len);
171 } else if (nonce_len == CHACHA20_NONCE_LEN_IETF) {
172 /* RFC 7539, May 2015 */
173
174 ctr = (uint64_t)(nonce[0] | nonce[1] << 8 |
175 nonce[2] << 16 | nonce[3] << 24) << 32;
176 iv = nonce + CHACHA20_CONSTANT_LEN;
177
178 memset(poly1305_key, 0, sizeof(poly1305_key));
179 CRYPTO_chacha_20(poly1305_key, poly1305_key,
180 sizeof(poly1305_key), c20_ctx->key, iv, ctr);
181
182 CRYPTO_poly1305_init(&poly1305, poly1305_key);
183 poly1305_update_with_pad16(&poly1305, ad, ad_len);
184 CRYPTO_chacha_20(out, in, in_len, c20_ctx->key, iv, ctr + 1);
185 poly1305_update_with_pad16(&poly1305, out, in_len);
186 poly1305_update_with_length(&poly1305, NULL, ad_len);
187 poly1305_update_with_length(&poly1305, NULL, in_len);
188 }
137 189
138 if (c20_ctx->tag_len != POLY1305_TAG_LEN) { 190 if (c20_ctx->tag_len != POLY1305_TAG_LEN) {
139 unsigned char tag[POLY1305_TAG_LEN]; 191 unsigned char tag[POLY1305_TAG_LEN];
@@ -157,9 +209,11 @@ aead_chacha20_poly1305_open(const EVP_AEAD_CTX *ctx, unsigned char *out,
157 const struct aead_chacha20_poly1305_ctx *c20_ctx = ctx->aead_state; 209 const struct aead_chacha20_poly1305_ctx *c20_ctx = ctx->aead_state;
158 unsigned char mac[POLY1305_TAG_LEN]; 210 unsigned char mac[POLY1305_TAG_LEN];
159 unsigned char poly1305_key[32]; 211 unsigned char poly1305_key[32];
212 const unsigned char *iv;
160 poly1305_state poly1305; 213 poly1305_state poly1305;
161 const uint64_t in_len_64 = in_len; 214 const uint64_t in_len_64 = in_len;
162 size_t plaintext_len; 215 size_t plaintext_len;
216 uint64_t ctr;
163 217
164 if (in_len < c20_ctx->tag_len) { 218 if (in_len < c20_ctx->tag_len) {
165 EVPerr(EVP_F_AEAD_CHACHA20_POLY1305_OPEN, EVP_R_BAD_DECRYPT); 219 EVPerr(EVP_F_AEAD_CHACHA20_POLY1305_OPEN, EVP_R_BAD_DECRYPT);
@@ -178,7 +232,7 @@ aead_chacha20_poly1305_open(const EVP_AEAD_CTX *ctx, unsigned char *out,
178 return 0; 232 return 0;
179 } 233 }
180 234
181 if (nonce_len != CHACHA20_NONCE_LEN) { 235 if (nonce_len != ctx->aead->nonce_len) {
182 EVPerr(EVP_F_AEAD_CHACHA20_POLY1305_OPEN, EVP_R_IV_TOO_LARGE); 236 EVPerr(EVP_F_AEAD_CHACHA20_POLY1305_OPEN, EVP_R_IV_TOO_LARGE);
183 return 0; 237 return 0;
184 } 238 }
@@ -191,13 +245,34 @@ aead_chacha20_poly1305_open(const EVP_AEAD_CTX *ctx, unsigned char *out,
191 return 0; 245 return 0;
192 } 246 }
193 247
194 memset(poly1305_key, 0, sizeof(poly1305_key)); 248 if (nonce_len == CHACHA20_NONCE_LEN) {
195 CRYPTO_chacha_20(poly1305_key, poly1305_key, sizeof(poly1305_key), 249 /* Google's draft-agl-tls-chacha20poly1305-04, Nov 2013 */
196 c20_ctx->key, nonce, 0); 250
251 memset(poly1305_key, 0, sizeof(poly1305_key));
252 CRYPTO_chacha_20(poly1305_key, poly1305_key,
253 sizeof(poly1305_key), c20_ctx->key, nonce, 0);
254
255 CRYPTO_poly1305_init(&poly1305, poly1305_key);
256 poly1305_update_with_length(&poly1305, ad, ad_len);
257 poly1305_update_with_length(&poly1305, in, plaintext_len);
258 } else if (nonce_len == CHACHA20_NONCE_LEN_IETF) {
259 /* RFC 7539, May 2015 */
260
261 ctr = (uint64_t)(nonce[0] | nonce[1] << 8 |
262 nonce[2] << 16 | nonce[3] << 24) << 32;
263 iv = nonce + CHACHA20_CONSTANT_LEN;
264
265 memset(poly1305_key, 0, sizeof(poly1305_key));
266 CRYPTO_chacha_20(poly1305_key, poly1305_key,
267 sizeof(poly1305_key), c20_ctx->key, iv, ctr);
268
269 CRYPTO_poly1305_init(&poly1305, poly1305_key);
270 poly1305_update_with_pad16(&poly1305, ad, ad_len);
271 poly1305_update_with_pad16(&poly1305, in, plaintext_len);
272 poly1305_update_with_length(&poly1305, NULL, ad_len);
273 poly1305_update_with_length(&poly1305, NULL, plaintext_len);
274 }
197 275
198 CRYPTO_poly1305_init(&poly1305, poly1305_key);
199 poly1305_update_with_length(&poly1305, ad, ad_len);
200 poly1305_update_with_length(&poly1305, in, plaintext_len);
201 CRYPTO_poly1305_finish(&poly1305, mac); 276 CRYPTO_poly1305_finish(&poly1305, mac);
202 277
203 if (timingsafe_memcmp(mac, in + plaintext_len, c20_ctx->tag_len) != 0) { 278 if (timingsafe_memcmp(mac, in + plaintext_len, c20_ctx->tag_len) != 0) {
@@ -222,10 +297,28 @@ static const EVP_AEAD aead_chacha20_poly1305 = {
222 .open = aead_chacha20_poly1305_open, 297 .open = aead_chacha20_poly1305_open,
223}; 298};
224 299
300static const EVP_AEAD aead_chacha20_poly1305_ietf = {
301 .key_len = 32,
302 .nonce_len = CHACHA20_NONCE_LEN_IETF,
303 .overhead = POLY1305_TAG_LEN,
304 .max_tag_len = POLY1305_TAG_LEN,
305
306 .init = aead_chacha20_poly1305_init,
307 .cleanup = aead_chacha20_poly1305_cleanup,
308 .seal = aead_chacha20_poly1305_seal,
309 .open = aead_chacha20_poly1305_open,
310};
311
225const EVP_AEAD * 312const EVP_AEAD *
226EVP_aead_chacha20_poly1305() 313EVP_aead_chacha20_poly1305()
227{ 314{
228 return &aead_chacha20_poly1305; 315 return &aead_chacha20_poly1305;
229} 316}
230 317
318const EVP_AEAD *
319EVP_aead_chacha20_poly1305_ietf()
320{
321 return &aead_chacha20_poly1305_ietf;
322}
323
231#endif /* !OPENSSL_NO_CHACHA && !OPENSSL_NO_POLY1305 */ 324#endif /* !OPENSSL_NO_CHACHA && !OPENSSL_NO_POLY1305 */
diff --git a/src/lib/libcrypto/evp/evp.h b/src/lib/libcrypto/evp/evp.h
index 2ddbf6142e..1ec24879c0 100644
--- a/src/lib/libcrypto/evp/evp.h
+++ b/src/lib/libcrypto/evp/evp.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: evp.h,v 1.48 2015/09/14 01:45:03 doug Exp $ */ 1/* $OpenBSD: evp.h,v 1.49 2015/11/02 15:40:53 reyk Exp $ */
2/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) 2/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
3 * All rights reserved. 3 * All rights reserved.
4 * 4 *
@@ -1215,6 +1215,7 @@ const EVP_AEAD *EVP_aead_aes_256_gcm(void);
1215#if !defined(OPENSSL_NO_CHACHA) && !defined(OPENSSL_NO_POLY1305) 1215#if !defined(OPENSSL_NO_CHACHA) && !defined(OPENSSL_NO_POLY1305)
1216/* EVP_aead_chacha20_poly1305 is ChaCha20 with a Poly1305 authenticator. */ 1216/* EVP_aead_chacha20_poly1305 is ChaCha20 with a Poly1305 authenticator. */
1217const EVP_AEAD *EVP_aead_chacha20_poly1305(void); 1217const EVP_AEAD *EVP_aead_chacha20_poly1305(void);
1218const EVP_AEAD *EVP_aead_chacha20_poly1305_ietf(void);
1218#endif 1219#endif
1219 1220
1220/* EVP_AEAD_key_length returns the length of the keys used. */ 1221/* EVP_AEAD_key_length returns the length of the keys used. */
diff --git a/src/lib/libcrypto/man/EVP_AEAD_CTX_init.3 b/src/lib/libcrypto/man/EVP_AEAD_CTX_init.3
index a2b4efea54..e6abc282d3 100644
--- a/src/lib/libcrypto/man/EVP_AEAD_CTX_init.3
+++ b/src/lib/libcrypto/man/EVP_AEAD_CTX_init.3
@@ -1,4 +1,4 @@
1.\" $OpenBSD: EVP_AEAD_CTX_init.3,v 1.2 2015/10/14 09:11:25 schwarze Exp $ 1.\" $OpenBSD: EVP_AEAD_CTX_init.3,v 1.3 2015/11/02 15:40:53 reyk Exp $
2.\" 2.\"
3.\" Copyright (c) 2014, Google Inc. 3.\" Copyright (c) 2014, Google Inc.
4.\" Parts of the text were written by Adam Langley and David Benjamin. 4.\" Parts of the text were written by Adam Langley and David Benjamin.
@@ -16,7 +16,7 @@
16.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18.\" 18.\"
19.Dd $Mdocdate: October 14 2015 $ 19.Dd $Mdocdate: November 2 2015 $
20.Dt EVP_AEAD_CTX_INIT 3 20.Dt EVP_AEAD_CTX_INIT 3
21.Os 21.Os
22.Sh NAME 22.Sh NAME
@@ -30,7 +30,8 @@
30.Nm EVP_AEAD_nonce_length , 30.Nm EVP_AEAD_nonce_length ,
31.Nm EVP_aead_aes_128_gcm , 31.Nm EVP_aead_aes_128_gcm ,
32.Nm EVP_aead_aes_256_gcm , 32.Nm EVP_aead_aes_256_gcm ,
33.Nm EVP_aead_chacha20_poly1305 33.Nm EVP_aead_chacha20_poly1305 ,
34.Nm EVP_aead_chacha20_poly1305_ietf
34.Nd authenticated encryption with additional data 35.Nd authenticated encryption with additional data
35.Sh SYNOPSIS 36.Sh SYNOPSIS
36.In openssl/evp.h 37.In openssl/evp.h
@@ -101,6 +102,10 @@
101.Fo EVP_aead_chacha20_poly1305 102.Fo EVP_aead_chacha20_poly1305
102.Fa void 103.Fa void
103.Fc 104.Fc
105.Ft const EVP_AEAD *
106.Fo EVP_aead_chacha20_poly1305_ietf
107.Fa void
108.Fc
104.Sh DESCRIPTION 109.Sh DESCRIPTION
105AEAD (Authenticated Encryption with Additional Data) couples 110AEAD (Authenticated Encryption with Additional Data) couples
106confidentiality and integrity in a single primitive. 111confidentiality and integrity in a single primitive.
@@ -219,6 +224,11 @@ AES-128 in Galois Counter Mode.
219AES-256 in Galois Counter Mode. 224AES-256 in Galois Counter Mode.
220.It Fn EVP_aead_chacha20_poly1305 225.It Fn EVP_aead_chacha20_poly1305
221ChaCha20 with a Poly1305 authenticator. 226ChaCha20 with a Poly1305 authenticator.
227.It Fn EVP_aead_chacha20_poly1305_ietf
228ChaCha20 with a Poly1305 authenticator for IETF Protocols.
229The IETF standardised variant of the AEAD is incompatible with the
230original version.
231It uses a constant salt that is prepended to the nonce.
222.El 232.El
223.Pp 233.Pp
224Where possible the 234Where possible the
@@ -270,6 +280,23 @@ EVP_AEAD_CTX_cleanup(&ctx);
270.Ed 280.Ed
271.Sh SEE ALSO 281.Sh SEE ALSO
272.Xr evp 3 282.Xr evp 3
283.Sh STANDARDS
284.Rs
285.%A A. Langley
286.%A W. Chang
287.%D November 2013
288.%R draft-agl-tls-chacha20poly1305-04
289.%T ChaCha20 and Poly1305 based Cipher Suites for TLS
290.Re
291.Pp
292.Rs
293.%A Y. Nir
294.%A A. Langley
295.%D May 2015
296.%R RFC 7539
297.%T ChaCha20 and Poly1305 for IETF Protocols
298.Re
299.Pp
273.Sh HISTORY 300.Sh HISTORY
274AEAD is based on the implementation by 301AEAD is based on the implementation by
275.An Adam Langley 302.An Adam Langley
diff --git a/src/lib/libssl/src/crypto/evp/e_chacha20poly1305.c b/src/lib/libssl/src/crypto/evp/e_chacha20poly1305.c
index 9deb40b72a..47551c4578 100644
--- a/src/lib/libssl/src/crypto/evp/e_chacha20poly1305.c
+++ b/src/lib/libssl/src/crypto/evp/e_chacha20poly1305.c
@@ -1,5 +1,7 @@
1/* $OpenBSD: e_chacha20poly1305.c,v 1.10 2015/09/10 15:56:25 jsing Exp $ */ 1/* $OpenBSD: e_chacha20poly1305.c,v 1.11 2015/11/02 15:40:53 reyk Exp $ */
2
2/* 3/*
4 * Copyright (c) 2015 Reyk Floter <reyk@openbsd.org>
3 * Copyright (c) 2014, Google Inc. 5 * Copyright (c) 2014, Google Inc.
4 * 6 *
5 * Permission to use, copy, modify, and/or distribute this software for any 7 * Permission to use, copy, modify, and/or distribute this software for any
@@ -32,6 +34,16 @@
32#define POLY1305_TAG_LEN 16 34#define POLY1305_TAG_LEN 16
33#define CHACHA20_NONCE_LEN 8 35#define CHACHA20_NONCE_LEN 8
34 36
37/*
38 * The informational RFC 7539, "ChaCha20 and Poly1305 for IETF Protocols",
39 * introduced a modified AEAD construction that is incompatible with the
40 * common style that that has been already used in TLS. The IETF version
41 * also adds a constant (salt) that is prepended to the nonce.
42 */
43#define CHACHA20_CONSTANT_LEN 4
44#define CHACHA20_IV_LEN 8
45#define CHACHA20_NONCE_LEN_IETF (CHACHA20_CONSTANT_LEN + CHACHA20_IV_LEN)
46
35struct aead_chacha20_poly1305_ctx { 47struct aead_chacha20_poly1305_ctx {
36 unsigned char key[32]; 48 unsigned char key[32];
37 unsigned char tag_len; 49 unsigned char tag_len;
@@ -88,10 +100,27 @@ poly1305_update_with_length(poly1305_state *poly1305,
88 j >>= 8; 100 j >>= 8;
89 } 101 }
90 102
91 CRYPTO_poly1305_update(poly1305, data, data_len); 103 if (data != NULL)
104 CRYPTO_poly1305_update(poly1305, data, data_len);
92 CRYPTO_poly1305_update(poly1305, length_bytes, sizeof(length_bytes)); 105 CRYPTO_poly1305_update(poly1305, length_bytes, sizeof(length_bytes));
93} 106}
94 107
108static void
109poly1305_update_with_pad16(poly1305_state *poly1305,
110 const unsigned char *data, size_t data_len)
111{
112 static const unsigned char zero_pad16[16];
113 size_t pad_len;
114
115 CRYPTO_poly1305_update(poly1305, data, data_len);
116
117 /* pad16() is defined in RFC 7539 2.8.1. */
118 if ((pad_len = data_len % 16) == 0)
119 return;
120
121 CRYPTO_poly1305_update(poly1305, zero_pad16, 16 - pad_len);
122}
123
95static int 124static int
96aead_chacha20_poly1305_seal(const EVP_AEAD_CTX *ctx, unsigned char *out, 125aead_chacha20_poly1305_seal(const EVP_AEAD_CTX *ctx, unsigned char *out,
97 size_t *out_len, size_t max_out_len, const unsigned char *nonce, 126 size_t *out_len, size_t max_out_len, const unsigned char *nonce,
@@ -101,7 +130,9 @@ aead_chacha20_poly1305_seal(const EVP_AEAD_CTX *ctx, unsigned char *out,
101 const struct aead_chacha20_poly1305_ctx *c20_ctx = ctx->aead_state; 130 const struct aead_chacha20_poly1305_ctx *c20_ctx = ctx->aead_state;
102 unsigned char poly1305_key[32]; 131 unsigned char poly1305_key[32];
103 poly1305_state poly1305; 132 poly1305_state poly1305;
133 const unsigned char *iv;
104 const uint64_t in_len_64 = in_len; 134 const uint64_t in_len_64 = in_len;
135 uint64_t ctr;
105 136
106 /* The underlying ChaCha implementation may not overflow the block 137 /* The underlying ChaCha implementation may not overflow the block
107 * counter into the second counter word. Therefore we disallow 138 * counter into the second counter word. Therefore we disallow
@@ -121,19 +152,40 @@ aead_chacha20_poly1305_seal(const EVP_AEAD_CTX *ctx, unsigned char *out,
121 return 0; 152 return 0;
122 } 153 }
123 154
124 if (nonce_len != CHACHA20_NONCE_LEN) { 155 if (nonce_len != ctx->aead->nonce_len) {
125 EVPerr(EVP_F_AEAD_CHACHA20_POLY1305_SEAL, EVP_R_IV_TOO_LARGE); 156 EVPerr(EVP_F_AEAD_CHACHA20_POLY1305_SEAL, EVP_R_IV_TOO_LARGE);
126 return 0; 157 return 0;
127 } 158 }
128 159
129 memset(poly1305_key, 0, sizeof(poly1305_key)); 160 if (nonce_len == CHACHA20_NONCE_LEN) {
130 CRYPTO_chacha_20(poly1305_key, poly1305_key, sizeof(poly1305_key), 161 /* Google's draft-agl-tls-chacha20poly1305-04, Nov 2013 */
131 c20_ctx->key, nonce, 0); 162
132 163 memset(poly1305_key, 0, sizeof(poly1305_key));
133 CRYPTO_poly1305_init(&poly1305, poly1305_key); 164 CRYPTO_chacha_20(poly1305_key, poly1305_key,
134 poly1305_update_with_length(&poly1305, ad, ad_len); 165 sizeof(poly1305_key), c20_ctx->key, nonce, 0);
135 CRYPTO_chacha_20(out, in, in_len, c20_ctx->key, nonce, 1); 166
136 poly1305_update_with_length(&poly1305, out, in_len); 167 CRYPTO_poly1305_init(&poly1305, poly1305_key);
168 poly1305_update_with_length(&poly1305, ad, ad_len);
169 CRYPTO_chacha_20(out, in, in_len, c20_ctx->key, nonce, 1);
170 poly1305_update_with_length(&poly1305, out, in_len);
171 } else if (nonce_len == CHACHA20_NONCE_LEN_IETF) {
172 /* RFC 7539, May 2015 */
173
174 ctr = (uint64_t)(nonce[0] | nonce[1] << 8 |
175 nonce[2] << 16 | nonce[3] << 24) << 32;
176 iv = nonce + CHACHA20_CONSTANT_LEN;
177
178 memset(poly1305_key, 0, sizeof(poly1305_key));
179 CRYPTO_chacha_20(poly1305_key, poly1305_key,
180 sizeof(poly1305_key), c20_ctx->key, iv, ctr);
181
182 CRYPTO_poly1305_init(&poly1305, poly1305_key);
183 poly1305_update_with_pad16(&poly1305, ad, ad_len);
184 CRYPTO_chacha_20(out, in, in_len, c20_ctx->key, iv, ctr + 1);
185 poly1305_update_with_pad16(&poly1305, out, in_len);
186 poly1305_update_with_length(&poly1305, NULL, ad_len);
187 poly1305_update_with_length(&poly1305, NULL, in_len);
188 }
137 189
138 if (c20_ctx->tag_len != POLY1305_TAG_LEN) { 190 if (c20_ctx->tag_len != POLY1305_TAG_LEN) {
139 unsigned char tag[POLY1305_TAG_LEN]; 191 unsigned char tag[POLY1305_TAG_LEN];
@@ -157,9 +209,11 @@ aead_chacha20_poly1305_open(const EVP_AEAD_CTX *ctx, unsigned char *out,
157 const struct aead_chacha20_poly1305_ctx *c20_ctx = ctx->aead_state; 209 const struct aead_chacha20_poly1305_ctx *c20_ctx = ctx->aead_state;
158 unsigned char mac[POLY1305_TAG_LEN]; 210 unsigned char mac[POLY1305_TAG_LEN];
159 unsigned char poly1305_key[32]; 211 unsigned char poly1305_key[32];
212 const unsigned char *iv;
160 poly1305_state poly1305; 213 poly1305_state poly1305;
161 const uint64_t in_len_64 = in_len; 214 const uint64_t in_len_64 = in_len;
162 size_t plaintext_len; 215 size_t plaintext_len;
216 uint64_t ctr;
163 217
164 if (in_len < c20_ctx->tag_len) { 218 if (in_len < c20_ctx->tag_len) {
165 EVPerr(EVP_F_AEAD_CHACHA20_POLY1305_OPEN, EVP_R_BAD_DECRYPT); 219 EVPerr(EVP_F_AEAD_CHACHA20_POLY1305_OPEN, EVP_R_BAD_DECRYPT);
@@ -178,7 +232,7 @@ aead_chacha20_poly1305_open(const EVP_AEAD_CTX *ctx, unsigned char *out,
178 return 0; 232 return 0;
179 } 233 }
180 234
181 if (nonce_len != CHACHA20_NONCE_LEN) { 235 if (nonce_len != ctx->aead->nonce_len) {
182 EVPerr(EVP_F_AEAD_CHACHA20_POLY1305_OPEN, EVP_R_IV_TOO_LARGE); 236 EVPerr(EVP_F_AEAD_CHACHA20_POLY1305_OPEN, EVP_R_IV_TOO_LARGE);
183 return 0; 237 return 0;
184 } 238 }
@@ -191,13 +245,34 @@ aead_chacha20_poly1305_open(const EVP_AEAD_CTX *ctx, unsigned char *out,
191 return 0; 245 return 0;
192 } 246 }
193 247
194 memset(poly1305_key, 0, sizeof(poly1305_key)); 248 if (nonce_len == CHACHA20_NONCE_LEN) {
195 CRYPTO_chacha_20(poly1305_key, poly1305_key, sizeof(poly1305_key), 249 /* Google's draft-agl-tls-chacha20poly1305-04, Nov 2013 */
196 c20_ctx->key, nonce, 0); 250
251 memset(poly1305_key, 0, sizeof(poly1305_key));
252 CRYPTO_chacha_20(poly1305_key, poly1305_key,
253 sizeof(poly1305_key), c20_ctx->key, nonce, 0);
254
255 CRYPTO_poly1305_init(&poly1305, poly1305_key);
256 poly1305_update_with_length(&poly1305, ad, ad_len);
257 poly1305_update_with_length(&poly1305, in, plaintext_len);
258 } else if (nonce_len == CHACHA20_NONCE_LEN_IETF) {
259 /* RFC 7539, May 2015 */
260
261 ctr = (uint64_t)(nonce[0] | nonce[1] << 8 |
262 nonce[2] << 16 | nonce[3] << 24) << 32;
263 iv = nonce + CHACHA20_CONSTANT_LEN;
264
265 memset(poly1305_key, 0, sizeof(poly1305_key));
266 CRYPTO_chacha_20(poly1305_key, poly1305_key,
267 sizeof(poly1305_key), c20_ctx->key, iv, ctr);
268
269 CRYPTO_poly1305_init(&poly1305, poly1305_key);
270 poly1305_update_with_pad16(&poly1305, ad, ad_len);
271 poly1305_update_with_pad16(&poly1305, in, plaintext_len);
272 poly1305_update_with_length(&poly1305, NULL, ad_len);
273 poly1305_update_with_length(&poly1305, NULL, plaintext_len);
274 }
197 275
198 CRYPTO_poly1305_init(&poly1305, poly1305_key);
199 poly1305_update_with_length(&poly1305, ad, ad_len);
200 poly1305_update_with_length(&poly1305, in, plaintext_len);
201 CRYPTO_poly1305_finish(&poly1305, mac); 276 CRYPTO_poly1305_finish(&poly1305, mac);
202 277
203 if (timingsafe_memcmp(mac, in + plaintext_len, c20_ctx->tag_len) != 0) { 278 if (timingsafe_memcmp(mac, in + plaintext_len, c20_ctx->tag_len) != 0) {
@@ -222,10 +297,28 @@ static const EVP_AEAD aead_chacha20_poly1305 = {
222 .open = aead_chacha20_poly1305_open, 297 .open = aead_chacha20_poly1305_open,
223}; 298};
224 299
300static const EVP_AEAD aead_chacha20_poly1305_ietf = {
301 .key_len = 32,
302 .nonce_len = CHACHA20_NONCE_LEN_IETF,
303 .overhead = POLY1305_TAG_LEN,
304 .max_tag_len = POLY1305_TAG_LEN,
305
306 .init = aead_chacha20_poly1305_init,
307 .cleanup = aead_chacha20_poly1305_cleanup,
308 .seal = aead_chacha20_poly1305_seal,
309 .open = aead_chacha20_poly1305_open,
310};
311
225const EVP_AEAD * 312const EVP_AEAD *
226EVP_aead_chacha20_poly1305() 313EVP_aead_chacha20_poly1305()
227{ 314{
228 return &aead_chacha20_poly1305; 315 return &aead_chacha20_poly1305;
229} 316}
230 317
318const EVP_AEAD *
319EVP_aead_chacha20_poly1305_ietf()
320{
321 return &aead_chacha20_poly1305_ietf;
322}
323
231#endif /* !OPENSSL_NO_CHACHA && !OPENSSL_NO_POLY1305 */ 324#endif /* !OPENSSL_NO_CHACHA && !OPENSSL_NO_POLY1305 */
diff --git a/src/lib/libssl/src/crypto/evp/evp.h b/src/lib/libssl/src/crypto/evp/evp.h
index 2ddbf6142e..1ec24879c0 100644
--- a/src/lib/libssl/src/crypto/evp/evp.h
+++ b/src/lib/libssl/src/crypto/evp/evp.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: evp.h,v 1.48 2015/09/14 01:45:03 doug Exp $ */ 1/* $OpenBSD: evp.h,v 1.49 2015/11/02 15:40:53 reyk Exp $ */
2/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) 2/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
3 * All rights reserved. 3 * All rights reserved.
4 * 4 *
@@ -1215,6 +1215,7 @@ const EVP_AEAD *EVP_aead_aes_256_gcm(void);
1215#if !defined(OPENSSL_NO_CHACHA) && !defined(OPENSSL_NO_POLY1305) 1215#if !defined(OPENSSL_NO_CHACHA) && !defined(OPENSSL_NO_POLY1305)
1216/* EVP_aead_chacha20_poly1305 is ChaCha20 with a Poly1305 authenticator. */ 1216/* EVP_aead_chacha20_poly1305 is ChaCha20 with a Poly1305 authenticator. */
1217const EVP_AEAD *EVP_aead_chacha20_poly1305(void); 1217const EVP_AEAD *EVP_aead_chacha20_poly1305(void);
1218const EVP_AEAD *EVP_aead_chacha20_poly1305_ietf(void);
1218#endif 1219#endif
1219 1220
1220/* EVP_AEAD_key_length returns the length of the keys used. */ 1221/* EVP_AEAD_key_length returns the length of the keys used. */