Revert "Remove old ChaCha20-Poly1305 AEAD."
This reverts commit def9b46801181c8854f35663a4c26c70843d430a.
(I should have uploaded a new version before sending to the commit queue.)
Change-Id: Iaead89c8d7fc1f56e6294d869db9238b467f520a
Reviewed-on: https://boringssl-review.googlesource.com/13202
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: Adam Langley <agl@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
diff --git a/crypto/cipher/aead_test.cc b/crypto/cipher/aead_test.cc
index 5ec8af3..0c95fb4 100644
--- a/crypto/cipher/aead_test.cc
+++ b/crypto/cipher/aead_test.cc
@@ -314,6 +314,7 @@
{ "aes-128-gcm-siv", EVP_aead_aes_128_gcm_siv, false },
{ "aes-256-gcm-siv", EVP_aead_aes_256_gcm_siv, false },
{ "chacha20-poly1305", EVP_aead_chacha20_poly1305, false },
+ { "chacha20-poly1305-old", EVP_aead_chacha20_poly1305_old, false },
{ "aes-128-cbc-sha1-tls", EVP_aead_aes_128_cbc_sha1_tls, true },
{ "aes-128-cbc-sha1-tls-implicit-iv", EVP_aead_aes_128_cbc_sha1_tls_implicit_iv, true },
{ "aes-128-cbc-sha256-tls", EVP_aead_aes_128_cbc_sha256_tls, true },
diff --git a/crypto/cipher/e_chacha20poly1305.c b/crypto/cipher/e_chacha20poly1305.c
index 88b78bb..ed0d74c 100644
--- a/crypto/cipher/e_chacha20poly1305.c
+++ b/crypto/cipher/e_chacha20poly1305.c
@@ -242,3 +242,59 @@
const EVP_AEAD *EVP_aead_chacha20_poly1305(void) {
return &aead_chacha20_poly1305;
}
+
+static void poly1305_update_old(poly1305_state *ctx, const uint8_t *ad,
+ size_t ad_len, const uint8_t *ciphertext,
+ size_t ciphertext_len) {
+ CRYPTO_poly1305_update(ctx, ad, ad_len);
+ poly1305_update_length(ctx, ad_len);
+ CRYPTO_poly1305_update(ctx, ciphertext, ciphertext_len);
+ poly1305_update_length(ctx, ciphertext_len);
+}
+
+static int aead_chacha20_poly1305_old_seal(
+ const EVP_AEAD_CTX *ctx, uint8_t *out, size_t *out_len, size_t max_out_len,
+ const uint8_t *nonce, size_t nonce_len, const uint8_t *in, size_t in_len,
+ const uint8_t *ad, size_t ad_len) {
+ if (nonce_len != 8) {
+ OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_UNSUPPORTED_NONCE_SIZE);
+ return 0;
+ }
+ uint8_t nonce_96[12];
+ OPENSSL_memset(nonce_96, 0, 4);
+ OPENSSL_memcpy(nonce_96 + 4, nonce, 8);
+ return seal_impl(poly1305_update_old, ctx, out, out_len, max_out_len,
+ nonce_96, in, in_len, ad, ad_len);
+}
+
+static int aead_chacha20_poly1305_old_open(
+ const EVP_AEAD_CTX *ctx, uint8_t *out, size_t *out_len, size_t max_out_len,
+ const uint8_t *nonce, size_t nonce_len, const uint8_t *in, size_t in_len,
+ const uint8_t *ad, size_t ad_len) {
+ if (nonce_len != 8) {
+ OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_UNSUPPORTED_NONCE_SIZE);
+ return 0;
+ }
+ uint8_t nonce_96[12];
+ OPENSSL_memset(nonce_96, 0, 4);
+ OPENSSL_memcpy(nonce_96 + 4, nonce, 8);
+ return open_impl(poly1305_update_old, ctx, out, out_len, max_out_len,
+ nonce_96, in, in_len, ad, ad_len);
+}
+
+static const EVP_AEAD aead_chacha20_poly1305_old = {
+ 32, /* key len */
+ 8, /* nonce len */
+ POLY1305_TAG_LEN, /* overhead */
+ POLY1305_TAG_LEN, /* max tag length */
+ aead_chacha20_poly1305_init,
+ NULL, /* init_with_direction */
+ aead_chacha20_poly1305_cleanup,
+ aead_chacha20_poly1305_old_seal,
+ aead_chacha20_poly1305_old_open,
+ NULL, /* get_iv */
+};
+
+const EVP_AEAD *EVP_aead_chacha20_poly1305_old(void) {
+ return &aead_chacha20_poly1305_old;
+}
diff --git a/crypto/cipher/test/chacha20_poly1305_tests.txt b/crypto/cipher/test/chacha20_poly1305_tests.txt
index 018eb56..103c196 100644
--- a/crypto/cipher/test/chacha20_poly1305_tests.txt
+++ b/crypto/cipher/test/chacha20_poly1305_tests.txt
@@ -47,6 +47,9 @@
CT: e275aeb341e1fc9a70c4fd4496fc7cdb
TAG: 41acd0560ea6843d3e5d4e5babf6e946
+# Test vectors from chacha20_poly1305_old_tests.txt, modified for the RFC 7539
+# AEAD construction.
+
KEY: 9a97f65b9b4c721b960a672145fca8d4e32e67f9111ea979ce9c4826806aeee6
NONCE: 000000003de9c0da2bd7f91e
IN: ""
diff --git a/include/openssl/aead.h b/include/openssl/aead.h
index bd655d6..35e0f13 100644
--- a/include/openssl/aead.h
+++ b/include/openssl/aead.h
@@ -100,6 +100,11 @@
* Poly1305 as described in RFC 7539. */
OPENSSL_EXPORT const EVP_AEAD *EVP_aead_chacha20_poly1305(void);
+/* EVP_aead_chacha20_poly1305_old is an AEAD built from ChaCha20 and
+ * Poly1305 that is used in the experimental ChaCha20-Poly1305 TLS cipher
+ * suites. */
+OPENSSL_EXPORT const EVP_AEAD *EVP_aead_chacha20_poly1305_old(void);
+
/* EVP_aead_aes_128_ctr_hmac_sha256 is AES-128 in CTR mode with HMAC-SHA256 for
* authentication. The nonce is 12 bytes; the bottom 32-bits are used as the
* block counter, thus the maximum plaintext size is 64GB. */
diff --git a/include/openssl/tls1.h b/include/openssl/tls1.h
index 24edf55..4b3e1aa 100644
--- a/include/openssl/tls1.h
+++ b/include/openssl/tls1.h
@@ -411,6 +411,9 @@
#define TLS1_CK_ECDH_RSA_WITH_AES_128_GCM_SHA256 0x0300C031
#define TLS1_CK_ECDH_RSA_WITH_AES_256_GCM_SHA384 0x0300C032
+#define TLS1_CK_ECDHE_RSA_CHACHA20_POLY1305_OLD 0x0300CC13
+#define TLS1_CK_ECDHE_ECDSA_CHACHA20_POLY1305_OLD 0x0300CC14
+
/* ChaCha20-Poly1305 cipher suites from RFC 7905. */
#define TLS1_CK_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 0x0300CCA8
#define TLS1_CK_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 0x0300CCA9
@@ -586,6 +589,14 @@
#define TLS1_TXT_ECDH_RSA_WITH_AES_128_GCM_SHA256 "ECDH-RSA-AES128-GCM-SHA256"
#define TLS1_TXT_ECDH_RSA_WITH_AES_256_GCM_SHA384 "ECDH-RSA-AES256-GCM-SHA384"
+/* For convenience, the old and new CHACHA20_POLY1305 ciphers have the same
+ * name. In cipher strings, both will be selected. This is temporary and will be
+ * removed when the pre-standard construction is removed. */
+#define TLS1_TXT_ECDHE_RSA_WITH_CHACHA20_POLY1305_OLD \
+ "ECDHE-RSA-CHACHA20-POLY1305"
+#define TLS1_TXT_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_OLD \
+ "ECDHE-ECDSA-CHACHA20-POLY1305"
+
#define TLS1_TXT_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 \
"ECDHE-RSA-CHACHA20-POLY1305"
#define TLS1_TXT_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 \
diff --git a/ssl/internal.h b/ssl/internal.h
index 3ad6c96..eb47785 100644
--- a/ssl/internal.h
+++ b/ssl/internal.h
@@ -188,8 +188,9 @@
#define SSL_AES256 0x00000004L
#define SSL_AES128GCM 0x00000008L
#define SSL_AES256GCM 0x00000010L
-#define SSL_eNULL 0x00000020L
-#define SSL_CHACHA20POLY1305 0x00000040L
+#define SSL_CHACHA20POLY1305_OLD 0x00000020L
+#define SSL_eNULL 0x00000040L
+#define SSL_CHACHA20POLY1305 0x00000080L
#define SSL_AES (SSL_AES128 | SSL_AES256 | SSL_AES128GCM | SSL_AES256GCM)
diff --git a/ssl/ssl_cipher.c b/ssl/ssl_cipher.c
index 480304f..7ca79ab 100644
--- a/ssl/ssl_cipher.c
+++ b/ssl/ssl_cipher.c
@@ -542,6 +542,28 @@
/* ChaCha20-Poly1305 cipher suites. */
+#if !defined(BORINGSSL_ANDROID_SYSTEM)
+ {
+ TLS1_TXT_ECDHE_RSA_WITH_CHACHA20_POLY1305_OLD,
+ TLS1_CK_ECDHE_RSA_CHACHA20_POLY1305_OLD,
+ SSL_kECDHE,
+ SSL_aRSA,
+ SSL_CHACHA20POLY1305_OLD,
+ SSL_AEAD,
+ SSL_HANDSHAKE_MAC_SHA256,
+ },
+
+ {
+ TLS1_TXT_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_OLD,
+ TLS1_CK_ECDHE_ECDSA_CHACHA20_POLY1305_OLD,
+ SSL_kECDHE,
+ SSL_aECDSA,
+ SSL_CHACHA20POLY1305_OLD,
+ SSL_AEAD,
+ SSL_HANDSHAKE_MAC_SHA256,
+ },
+#endif
+
/* Cipher CCA8 */
{
TLS1_TXT_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
@@ -652,7 +674,8 @@
{"AES256", ~0u, ~0u, SSL_AES256 | SSL_AES256GCM, ~0u, 0},
{"AES", ~0u, ~0u, SSL_AES, ~0u, 0},
{"AESGCM", ~0u, ~0u, SSL_AES128GCM | SSL_AES256GCM, ~0u, 0},
- {"CHACHA20", ~0u, ~0u, SSL_CHACHA20POLY1305, ~0u, 0},
+ {"CHACHA20", ~0u, ~0u, SSL_CHACHA20POLY1305 | SSL_CHACHA20POLY1305_OLD, ~0u,
+ 0},
/* MAC aliases */
{"SHA1", ~0u, ~0u, ~SSL_eNULL, SSL_SHA1, 0},
@@ -709,6 +732,11 @@
} else if (cipher->algorithm_enc == SSL_AES256GCM) {
*out_aead = EVP_aead_aes_256_gcm();
*out_fixed_iv_len = 4;
+#if !defined(BORINGSSL_ANDROID_SYSTEM)
+ } else if (cipher->algorithm_enc == SSL_CHACHA20POLY1305_OLD) {
+ *out_aead = EVP_aead_chacha20_poly1305_old();
+ *out_fixed_iv_len = 0;
+#endif
} else if (cipher->algorithm_enc == SSL_CHACHA20POLY1305) {
*out_aead = EVP_aead_chacha20_poly1305();
*out_fixed_iv_len = 12;
@@ -1216,6 +1244,29 @@
multi = 1;
}
+ /* If one of the CHACHA20_POLY1305 variants is selected, include the other
+ * as well. They have the same name to avoid requiring changes in
+ * configuration. Apply this transformation late so that the cipher name
+ * still behaves as an exact name and not an alias in multipart rules.
+ *
+ * This is temporary and will be removed when the pre-standard construction
+ * is removed. */
+ if (cipher_id == TLS1_CK_ECDHE_RSA_CHACHA20_POLY1305_OLD ||
+ cipher_id == TLS1_CK_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256) {
+ cipher_id = 0;
+ alg_mkey = SSL_kECDHE;
+ alg_auth = SSL_aRSA;
+ alg_enc = SSL_CHACHA20POLY1305|SSL_CHACHA20POLY1305_OLD;
+ alg_mac = SSL_AEAD;
+ } else if (cipher_id == TLS1_CK_ECDHE_ECDSA_CHACHA20_POLY1305_OLD ||
+ cipher_id == TLS1_CK_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256) {
+ cipher_id = 0;
+ alg_mkey = SSL_kECDHE;
+ alg_auth = SSL_aECDSA;
+ alg_enc = SSL_CHACHA20POLY1305|SSL_CHACHA20POLY1305_OLD;
+ alg_mac = SSL_AEAD;
+ }
+
/* Ok, we have the rule, now apply it. */
if (rule == CIPHER_SPECIAL) {
/* special command */
@@ -1298,9 +1349,13 @@
&head, &tail);
ssl_cipher_apply_rule(0, ~0u, ~0u, SSL_CHACHA20POLY1305, ~0u, 0, CIPHER_ADD,
-1, 0, &head, &tail);
+ ssl_cipher_apply_rule(0, ~0u, ~0u, SSL_CHACHA20POLY1305_OLD, ~0u, 0,
+ CIPHER_ADD, -1, 0, &head, &tail);
} else {
ssl_cipher_apply_rule(0, ~0u, ~0u, SSL_CHACHA20POLY1305, ~0u, 0, CIPHER_ADD,
-1, 0, &head, &tail);
+ ssl_cipher_apply_rule(0, ~0u, ~0u, SSL_CHACHA20POLY1305_OLD, ~0u, 0,
+ CIPHER_ADD, -1, 0, &head, &tail);
ssl_cipher_apply_rule(0, ~0u, ~0u, SSL_AES128GCM, ~0u, 0, CIPHER_ADD, -1, 0,
&head, &tail);
ssl_cipher_apply_rule(0, ~0u, ~0u, SSL_AES256GCM, ~0u, 0, CIPHER_ADD, -1, 0,
@@ -1449,7 +1504,8 @@
}
int SSL_CIPHER_is_CHACHA20POLY1305(const SSL_CIPHER *cipher) {
- return (cipher->algorithm_enc & SSL_CHACHA20POLY1305) != 0;
+ return (cipher->algorithm_enc &
+ (SSL_CHACHA20POLY1305 | SSL_CHACHA20POLY1305_OLD)) != 0;
}
int SSL_CIPHER_is_NULL(const SSL_CIPHER *cipher) {
@@ -1566,6 +1622,7 @@
case SSL_AES256GCM:
return "AES_256_GCM";
case SSL_CHACHA20POLY1305:
+ case SSL_CHACHA20POLY1305_OLD:
return "CHACHA20_POLY1305";
break;
default:
@@ -1643,6 +1700,9 @@
case SSL_AES256:
case SSL_AES256GCM:
+#if !defined(BORINGSSL_ANDROID_SYSTEM)
+ case SSL_CHACHA20POLY1305_OLD:
+#endif
case SSL_CHACHA20POLY1305:
alg_bits = 256;
strength_bits = 256;
@@ -1748,6 +1808,10 @@
enc = "AESGCM(256)";
break;
+ case SSL_CHACHA20POLY1305_OLD:
+ enc = "ChaCha20-Poly1305-Old";
+ break;
+
case SSL_CHACHA20POLY1305:
enc = "ChaCha20-Poly1305";
break;
diff --git a/ssl/ssl_test.cc b/ssl/ssl_test.cc
index 5bc1675..952ac11 100644
--- a/ssl/ssl_test.cc
+++ b/ssl/ssl_test.cc
@@ -75,7 +75,9 @@
"ECDHE-RSA-AES128-GCM-SHA256",
{
{TLS1_CK_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, 0},
+ {TLS1_CK_ECDHE_ECDSA_CHACHA20_POLY1305_OLD, 0},
{TLS1_CK_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, 0},
+ {TLS1_CK_ECDHE_RSA_CHACHA20_POLY1305_OLD, 0},
{TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 0},
{TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256, 0},
},
@@ -89,8 +91,10 @@
"+aRSA",
{
{TLS1_CK_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, 0},
+ {TLS1_CK_ECDHE_ECDSA_CHACHA20_POLY1305_OLD, 0},
{TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 0},
{TLS1_CK_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, 0},
+ {TLS1_CK_ECDHE_RSA_CHACHA20_POLY1305_OLD, 0},
{TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256, 0},
},
},
@@ -103,6 +107,7 @@
"ECDHE-RSA-AES128-GCM-SHA256",
{
{TLS1_CK_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, 0},
+ {TLS1_CK_ECDHE_ECDSA_CHACHA20_POLY1305_OLD, 0},
{TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 0},
},
},
@@ -134,7 +139,9 @@
"BOGUS1:-BOGUS2:+BOGUS3:!BOGUS4",
{
{TLS1_CK_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, 0},
+ {TLS1_CK_ECDHE_ECDSA_CHACHA20_POLY1305_OLD, 0},
{TLS1_CK_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, 0},
+ {TLS1_CK_ECDHE_RSA_CHACHA20_POLY1305_OLD, 0},
{TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 0},
{TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256, 0},
},
@@ -146,8 +153,10 @@
"ECDHE-RSA-AES128-GCM-SHA256",
{
{TLS1_CK_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, 1},
+ {TLS1_CK_ECDHE_ECDSA_CHACHA20_POLY1305_OLD, 1},
{TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 0},
- {TLS1_CK_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, 0},
+ {TLS1_CK_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, 1},
+ {TLS1_CK_ECDHE_RSA_CHACHA20_POLY1305_OLD, 0},
{TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256, 0},
},
},
@@ -168,6 +177,7 @@
{
{TLS1_CK_ECDHE_RSA_WITH_AES_256_CBC_SHA, 0},
{TLS1_CK_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, 0},
+ {TLS1_CK_ECDHE_RSA_CHACHA20_POLY1305_OLD, 0},
{TLS1_CK_ECDHE_RSA_WITH_AES_128_CBC_SHA, 0},
{TLS1_CK_RSA_WITH_AES_128_SHA, 0},
{TLS1_CK_RSA_WITH_AES_256_SHA, 0},
@@ -217,7 +227,9 @@
"!ECDSA+ECDHE-ECDSA-CHACHA20-POLY1305",
{
{TLS1_CK_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, 0},
+ {TLS1_CK_ECDHE_ECDSA_CHACHA20_POLY1305_OLD, 0},
{TLS1_CK_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, 0},
+ {TLS1_CK_ECDHE_RSA_CHACHA20_POLY1305_OLD, 0},
},
},
};
@@ -778,6 +790,12 @@
{TLS1_CK_AES_256_GCM_SHA384, "TLS_AES_256_GCM_SHA384"},
{TLS1_CK_AES_128_GCM_SHA256, "TLS_AES_128_GCM_SHA256"},
{TLS1_CK_CHACHA20_POLY1305_SHA256, "TLS_CHACHA20_POLY1305_SHA256"},
+
+ // These names are non-standard:
+ {TLS1_CK_ECDHE_RSA_CHACHA20_POLY1305_OLD,
+ "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256"},
+ {TLS1_CK_ECDHE_ECDSA_CHACHA20_POLY1305_OLD,
+ "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256"},
};
static bool TestCipherGetRFCName(void) {
@@ -1929,20 +1947,20 @@
}
static const uint8_t kTLS12ClientHello[] = {
- 0x16, 0x03, 0x01, 0x00, 0x9a, 0x01, 0x00, 0x00, 0x96, 0x03, 0x03, 0x00,
+ 0x16, 0x03, 0x01, 0x00, 0x9e, 0x01, 0x00, 0x00, 0x9a, 0x03, 0x03, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0xcc, 0xa9,
- 0xcc, 0xa8, 0xc0, 0x2b, 0xc0, 0x2f, 0x00, 0x9e, 0xc0, 0x2c, 0xc0, 0x30,
- 0x00, 0x9f, 0xc0, 0x09, 0xc0, 0x23, 0xc0, 0x13, 0xc0, 0x27, 0x00, 0x33,
- 0x00, 0x67, 0xc0, 0x0a, 0xc0, 0x24, 0xc0, 0x14, 0xc0, 0x28, 0x00, 0x39,
- 0x00, 0x6b, 0x00, 0x9c, 0x00, 0x9d, 0x00, 0x2f, 0x00, 0x3c, 0x00, 0x35,
- 0x00, 0x3d, 0x00, 0x0a, 0x01, 0x00, 0x00, 0x37, 0xff, 0x01, 0x00, 0x01,
- 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x0d, 0x00,
- 0x14, 0x00, 0x12, 0x04, 0x03, 0x08, 0x04, 0x04, 0x01, 0x05, 0x03, 0x08,
- 0x05, 0x05, 0x01, 0x08, 0x06, 0x06, 0x01, 0x02, 0x01, 0x00, 0x0b, 0x00,
- 0x02, 0x01, 0x00, 0x00, 0x0a, 0x00, 0x08, 0x00, 0x06, 0x00, 0x1d, 0x00,
- 0x17, 0x00, 0x18,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3a, 0xcc, 0xa9,
+ 0xcc, 0xa8, 0xcc, 0x14, 0xcc, 0x13, 0xc0, 0x2b, 0xc0, 0x2f, 0x00, 0x9e,
+ 0xc0, 0x2c, 0xc0, 0x30, 0x00, 0x9f, 0xc0, 0x09, 0xc0, 0x23, 0xc0, 0x13,
+ 0xc0, 0x27, 0x00, 0x33, 0x00, 0x67, 0xc0, 0x0a, 0xc0, 0x24, 0xc0, 0x14,
+ 0xc0, 0x28, 0x00, 0x39, 0x00, 0x6b, 0x00, 0x9c, 0x00, 0x9d, 0x00, 0x2f,
+ 0x00, 0x3c, 0x00, 0x35, 0x00, 0x3d, 0x00, 0x0a, 0x01, 0x00, 0x00, 0x37,
+ 0xff, 0x01, 0x00, 0x01, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x23, 0x00,
+ 0x00, 0x00, 0x0d, 0x00, 0x14, 0x00, 0x12, 0x04, 0x03, 0x08, 0x04, 0x04,
+ 0x01, 0x05, 0x03, 0x08, 0x05, 0x05, 0x01, 0x08, 0x06, 0x06, 0x01, 0x02,
+ 0x01, 0x00, 0x0b, 0x00, 0x02, 0x01, 0x00, 0x00, 0x0a, 0x00, 0x08, 0x00,
+ 0x06, 0x00, 0x1d, 0x00, 0x17, 0x00, 0x18,
};
if (!ClientHelloMatches(TLS1_2_VERSION, kTLS12ClientHello,
sizeof(kTLS12ClientHello))) {
diff --git a/ssl/test/runner/chacha20_poly1305.go b/ssl/test/runner/chacha20_poly1305.go
index 866f724..f58e834 100644
--- a/ssl/test/runner/chacha20_poly1305.go
+++ b/ssl/test/runner/chacha20_poly1305.go
@@ -119,6 +119,9 @@
// RFC 7539 and draft-agl-tls-chacha20poly1305-04.
type chaCha20Poly1305 struct {
key [32]byte
+ // oldMode, if true, indicates that the draft spec should be
+ // implemented rather than the final, RFC version.
+ oldMode bool
}
func newChaCha20Poly1305(key []byte) (cipher.AEAD, error) {
@@ -130,8 +133,23 @@
return aead, nil
}
+func newChaCha20Poly1305Old(key []byte) (cipher.AEAD, error) {
+ if len(key) != 32 {
+ return nil, errors.New("bad key length")
+ }
+ aead := &chaCha20Poly1305{
+ oldMode: true,
+ }
+ copy(aead.key[:], key)
+ return aead, nil
+}
+
func (c *chaCha20Poly1305) NonceSize() int {
- return 12
+ if c.oldMode {
+ return 8
+ } else {
+ return 12
+ }
}
func (c *chaCha20Poly1305) Overhead() int { return 16 }
@@ -158,6 +176,21 @@
poly1305.Sum(tag, input, &poly1305Key)
}
+func (c *chaCha20Poly1305) poly1305Old(tag *[16]byte, nonce, ciphertext, additionalData []byte) {
+ input := make([]byte, 0, len(additionalData)+8+len(ciphertext)+8)
+ input = append(input, additionalData...)
+ input, out := sliceForAppend(input, 8)
+ binary.LittleEndian.PutUint64(out, uint64(len(additionalData)))
+ input = append(input, ciphertext...)
+ input, out = sliceForAppend(input, 8)
+ binary.LittleEndian.PutUint64(out, uint64(len(ciphertext)))
+
+ var poly1305Key [32]byte
+ chaCha20(poly1305Key[:], poly1305Key[:], c.key[:], nonce, 0)
+
+ poly1305.Sum(tag, input, &poly1305Key)
+}
+
func (c *chaCha20Poly1305) Seal(dst, nonce, plaintext, additionalData []byte) []byte {
if len(nonce) != c.NonceSize() {
panic("Bad nonce length")
@@ -167,7 +200,11 @@
chaCha20(out[:len(plaintext)], plaintext, c.key[:], nonce, 1)
var tag [16]byte
- c.poly1305(&tag, nonce, out[:len(plaintext)], additionalData)
+ if c.oldMode {
+ c.poly1305Old(&tag, nonce, out[:len(plaintext)], additionalData)
+ } else {
+ c.poly1305(&tag, nonce, out[:len(plaintext)], additionalData)
+ }
copy(out[len(plaintext):], tag[:])
return ret
@@ -183,7 +220,11 @@
plaintextLen := len(ciphertext) - 16
var tag [16]byte
- c.poly1305(&tag, nonce, ciphertext[:plaintextLen], additionalData)
+ if c.oldMode {
+ c.poly1305Old(&tag, nonce, ciphertext[:plaintextLen], additionalData)
+ } else {
+ c.poly1305(&tag, nonce, ciphertext[:plaintextLen], additionalData)
+ }
if subtle.ConstantTimeCompare(tag[:], ciphertext[plaintextLen:]) != 1 {
return nil, errors.New("chacha20: message authentication failed")
}
diff --git a/ssl/test/runner/chacha20_poly1305_test.go b/ssl/test/runner/chacha20_poly1305_test.go
index 38c4b70..e1597a4 100644
--- a/ssl/test/runner/chacha20_poly1305_test.go
+++ b/ssl/test/runner/chacha20_poly1305_test.go
@@ -88,6 +88,38 @@
return out
}
+// See draft-agl-tls-chacha20poly1305-04, section 7.
+func TestChaCha20Poly1305Old(t *testing.T) {
+ key := decodeHexOrPanic("4290bcb154173531f314af57f3be3b5006da371ece272afa1b5dbdd1100a1007")
+ input := decodeHexOrPanic("86d09974840bded2a5ca")
+ nonce := decodeHexOrPanic("cd7cf67be39c794a")
+ ad := decodeHexOrPanic("87e229d4500845a079c0")
+ output := decodeHexOrPanic("e3e446f7ede9a19b62a4677dabf4e3d24b876bb284753896e1d6")
+
+ aead, err := newChaCha20Poly1305Old(key)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ out, err := aead.Open(nil, nonce, output, ad)
+ if err != nil {
+ t.Errorf("Open failed: %s", err)
+ } else if !bytes.Equal(out, input) {
+ t.Errorf("Open gave %x, wanted %x", out, input)
+ }
+
+ out = aead.Seal(nil, nonce, input, ad)
+ if !bytes.Equal(out, output) {
+ t.Errorf("Open gave %x, wanted %x", out, output)
+ }
+
+ out[0]++
+ _, err = aead.Open(nil, nonce, out, ad)
+ if err == nil {
+ t.Errorf("Open on malformed data unexpectedly succeeded")
+ }
+}
+
var chaCha20Poly1305TestVectors = []struct {
key, input, nonce, ad, output string
}{
diff --git a/ssl/test/runner/cipher_suites.go b/ssl/test/runner/cipher_suites.go
index dd1bab6..fe283eb 100644
--- a/ssl/test/runner/cipher_suites.go
+++ b/ssl/test/runner/cipher_suites.go
@@ -106,6 +106,8 @@
{TLS_AES_256_GCM_SHA384, 32, 0, ivLenAESGCM, nil, suiteTLS13 | suiteSHA384, nil, nil, aeadAESGCM},
{TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, 32, 0, ivLenChaCha20Poly1305, ecdheECDSAKA, suiteECDHE | suiteECDSA | suiteTLS12, nil, nil, aeadCHACHA20POLY1305},
{TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, 32, 0, ivLenChaCha20Poly1305, ecdheRSAKA, suiteECDHE | suiteTLS12, nil, nil, aeadCHACHA20POLY1305},
+ {TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256_OLD, 32, 0, noIV, ecdheECDSAKA, suiteECDHE | suiteECDSA | suiteTLS12, nil, nil, aeadCHACHA20POLY1305Old},
+ {TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256_OLD, 32, 0, noIV, ecdheRSAKA, suiteECDHE | suiteTLS12, nil, nil, aeadCHACHA20POLY1305Old},
{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, 16, 0, ivLenAESGCM, ecdheRSAKA, suiteECDHE | suiteTLS12, nil, nil, aeadAESGCM},
{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 16, 0, ivLenAESGCM, ecdheECDSAKA, suiteECDHE | suiteECDSA | suiteTLS12, nil, nil, aeadAESGCM},
{TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, 32, 0, ivLenAESGCM, ecdheRSAKA, suiteECDHE | suiteTLS12 | suiteSHA384, nil, nil, aeadAESGCM},
@@ -294,6 +296,14 @@
return &tlsAead{&fixedNonceAEAD{nonce1, nonce2, aead}, true}
}
+func aeadCHACHA20POLY1305Old(version uint16, key, fixedNonce []byte) *tlsAead {
+ aead, err := newChaCha20Poly1305Old(key)
+ if err != nil {
+ panic(err)
+ }
+ return &tlsAead{aead, false}
+}
+
func xorSlice(out, in []byte) {
for i := range out {
out[i] ^= in[i]
@@ -509,6 +519,8 @@
// Additional cipher suite IDs, not IANA-assigned.
const (
+ TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256_OLD uint16 = 0xcc13
+ TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256_OLD uint16 = 0xcc14
TLS_AES_128_GCM_SHA256 uint16 = 0x1301
TLS_AES_256_GCM_SHA384 uint16 = 0x1302
TLS_CHACHA20_POLY1305_SHA256 uint16 = 0x1303
diff --git a/ssl/test/runner/runner.go b/ssl/test/runner/runner.go
index 54bfca5..3a884bc 100644
--- a/ssl/test/runner/runner.go
+++ b/ssl/test/runner/runner.go
@@ -1103,6 +1103,7 @@
{"ECDHE-ECDSA-AES256-SHA", TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA},
{"ECDHE-ECDSA-AES256-SHA384", TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384},
{"ECDHE-ECDSA-CHACHA20-POLY1305", TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256},
+ {"ECDHE-ECDSA-CHACHA20-POLY1305-OLD", TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256_OLD},
{"ECDHE-RSA-AES128-GCM", TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
{"ECDHE-RSA-AES128-SHA", TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
{"ECDHE-RSA-AES128-SHA256", TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256},
@@ -1110,6 +1111,7 @@
{"ECDHE-RSA-AES256-SHA", TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA},
{"ECDHE-RSA-AES256-SHA384", TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384},
{"ECDHE-RSA-CHACHA20-POLY1305", TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256},
+ {"ECDHE-RSA-CHACHA20-POLY1305-OLD", TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256_OLD},
{"PSK-AES128-CBC-SHA", TLS_PSK_WITH_AES_128_CBC_SHA},
{"PSK-AES256-CBC-SHA", TLS_PSK_WITH_AES_256_CBC_SHA},
{"ECDHE-PSK-AES128-CBC-SHA", TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA},
diff --git a/tool/speed.cc b/tool/speed.cc
index cf4d8ba..52708c0 100644
--- a/tool/speed.cc
+++ b/tool/speed.cc
@@ -618,6 +618,8 @@
!SpeedAEAD(EVP_aead_aes_256_gcm(), "AES-256-GCM", kTLSADLen, selected) ||
!SpeedAEAD(EVP_aead_chacha20_poly1305(), "ChaCha20-Poly1305", kTLSADLen,
selected) ||
+ !SpeedAEAD(EVP_aead_chacha20_poly1305_old(), "ChaCha20-Poly1305-Old",
+ kTLSADLen, selected) ||
!SpeedAEAD(EVP_aead_des_ede3_cbc_sha1_tls(), "DES-EDE3-CBC-SHA1",
kLegacyADLen, selected) ||
!SpeedAEAD(EVP_aead_aes_128_cbc_sha1_tls(), "AES-128-CBC-SHA1",
diff --git a/util/all_tests.json b/util/all_tests.json
index 2382893..a2f64aa 100644
--- a/util/all_tests.json
+++ b/util/all_tests.json
@@ -11,6 +11,7 @@
["crypto/cipher/aead_test", "aes-128-gcm-siv", "crypto/cipher/test/aes_128_gcm_siv_tests.txt"],
["crypto/cipher/aead_test", "aes-256-gcm-siv", "crypto/cipher/test/aes_256_gcm_siv_tests.txt"],
["crypto/cipher/aead_test", "chacha20-poly1305", "crypto/cipher/test/chacha20_poly1305_tests.txt"],
+ ["crypto/cipher/aead_test", "chacha20-poly1305-old", "crypto/cipher/test/chacha20_poly1305_old_tests.txt"],
["crypto/cipher/aead_test", "aes-128-cbc-sha1-tls", "crypto/cipher/test/aes_128_cbc_sha1_tls_tests.txt"],
["crypto/cipher/aead_test", "aes-128-cbc-sha1-tls-implicit-iv", "crypto/cipher/test/aes_128_cbc_sha1_tls_implicit_iv_tests.txt"],
["crypto/cipher/aead_test", "aes-128-cbc-sha256-tls", "crypto/cipher/test/aes_128_cbc_sha256_tls_tests.txt"],