diff options
author | reyk <> | 2015-11-02 15:40:53 +0000 |
---|---|---|
committer | reyk <> | 2015-11-02 15:40:53 +0000 |
commit | b743c75edf0dc70962a2ed0c5221ecb8841d7525 (patch) | |
tree | 40446be7b959dce9252457817e67737c7606706c /src/lib | |
parent | 3b76990c68663b08d77297a05a8104c2f1528064 (diff) | |
download | openbsd-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.c | 129 | ||||
-rw-r--r-- | src/lib/libcrypto/evp/evp.h | 3 | ||||
-rw-r--r-- | src/lib/libcrypto/man/EVP_AEAD_CTX_init.3 | 33 | ||||
-rw-r--r-- | src/lib/libssl/src/crypto/evp/e_chacha20poly1305.c | 129 | ||||
-rw-r--r-- | src/lib/libssl/src/crypto/evp/evp.h | 3 |
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 | |||
35 | struct aead_chacha20_poly1305_ctx { | 47 | struct 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 | ||
108 | static void | ||
109 | poly1305_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 | |||
95 | static int | 124 | static int |
96 | aead_chacha20_poly1305_seal(const EVP_AEAD_CTX *ctx, unsigned char *out, | 125 | aead_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 | ||
300 | static 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 | |||
225 | const EVP_AEAD * | 312 | const EVP_AEAD * |
226 | EVP_aead_chacha20_poly1305() | 313 | EVP_aead_chacha20_poly1305() |
227 | { | 314 | { |
228 | return &aead_chacha20_poly1305; | 315 | return &aead_chacha20_poly1305; |
229 | } | 316 | } |
230 | 317 | ||
318 | const EVP_AEAD * | ||
319 | EVP_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. */ |
1217 | const EVP_AEAD *EVP_aead_chacha20_poly1305(void); | 1217 | const EVP_AEAD *EVP_aead_chacha20_poly1305(void); |
1218 | const 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 |
105 | AEAD (Authenticated Encryption with Additional Data) couples | 110 | AEAD (Authenticated Encryption with Additional Data) couples |
106 | confidentiality and integrity in a single primitive. | 111 | confidentiality and integrity in a single primitive. |
@@ -219,6 +224,11 @@ AES-128 in Galois Counter Mode. | |||
219 | AES-256 in Galois Counter Mode. | 224 | AES-256 in Galois Counter Mode. |
220 | .It Fn EVP_aead_chacha20_poly1305 | 225 | .It Fn EVP_aead_chacha20_poly1305 |
221 | ChaCha20 with a Poly1305 authenticator. | 226 | ChaCha20 with a Poly1305 authenticator. |
227 | .It Fn EVP_aead_chacha20_poly1305_ietf | ||
228 | ChaCha20 with a Poly1305 authenticator for IETF Protocols. | ||
229 | The IETF standardised variant of the AEAD is incompatible with the | ||
230 | original version. | ||
231 | It uses a constant salt that is prepended to the nonce. | ||
222 | .El | 232 | .El |
223 | .Pp | 233 | .Pp |
224 | Where possible the | 234 | Where 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 |
274 | AEAD is based on the implementation by | 301 | AEAD 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 | |||
35 | struct aead_chacha20_poly1305_ctx { | 47 | struct 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 | ||
108 | static void | ||
109 | poly1305_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 | |||
95 | static int | 124 | static int |
96 | aead_chacha20_poly1305_seal(const EVP_AEAD_CTX *ctx, unsigned char *out, | 125 | aead_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 | ||
300 | static 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 | |||
225 | const EVP_AEAD * | 312 | const EVP_AEAD * |
226 | EVP_aead_chacha20_poly1305() | 313 | EVP_aead_chacha20_poly1305() |
227 | { | 314 | { |
228 | return &aead_chacha20_poly1305; | 315 | return &aead_chacha20_poly1305; |
229 | } | 316 | } |
230 | 317 | ||
318 | const EVP_AEAD * | ||
319 | EVP_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. */ |
1217 | const EVP_AEAD *EVP_aead_chacha20_poly1305(void); | 1217 | const EVP_AEAD *EVP_aead_chacha20_poly1305(void); |
1218 | const 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. */ |