ChaCha20-Poly1305 support.
diff --git a/ssl/s3_lib.c b/ssl/s3_lib.c
index 96b3a01..ae73161 100644
--- a/ssl/s3_lib.c
+++ b/ssl/s3_lib.c
@@ -1605,7 +1605,7 @@
SSL_AEAD,
SSL_TLSV1_2,
SSL_NOT_EXP|SSL_HIGH|SSL_FIPS,
- SSL_HANDSHAKE_MAC_SHA256|TLS1_PRF_SHA256|SSL_CIPHER_ALGORITHM2_AEAD|FIXED_NONCE_LEN(4),
+ SSL_HANDSHAKE_MAC_SHA256|TLS1_PRF_SHA256|SSL_CIPHER_ALGORITHM2_AEAD|FIXED_NONCE_LEN(4)|SSL_CIPHER_ALGORITHM2_VARIABLE_NONCE_INCLUDED_IN_RECORD,
128,
128,
},
@@ -1637,7 +1637,7 @@
SSL_AEAD,
SSL_TLSV1_2,
SSL_NOT_EXP|SSL_HIGH|SSL_FIPS,
- SSL_HANDSHAKE_MAC_SHA256|TLS1_PRF_SHA256|SSL_CIPHER_ALGORITHM2_AEAD|FIXED_NONCE_LEN(4),
+ SSL_HANDSHAKE_MAC_SHA256|TLS1_PRF_SHA256|SSL_CIPHER_ALGORITHM2_AEAD|FIXED_NONCE_LEN(4)|SSL_CIPHER_ALGORITHM2_VARIABLE_NONCE_INCLUDED_IN_RECORD,
128,
128,
},
@@ -1669,7 +1669,7 @@
SSL_AEAD,
SSL_TLSV1_2,
SSL_NOT_EXP|SSL_HIGH|SSL_FIPS,
- SSL_HANDSHAKE_MAC_SHA256|TLS1_PRF_SHA256|SSL_CIPHER_ALGORITHM2_AEAD|FIXED_NONCE_LEN(4),
+ SSL_HANDSHAKE_MAC_SHA256|TLS1_PRF_SHA256|SSL_CIPHER_ALGORITHM2_AEAD|FIXED_NONCE_LEN(4)|SSL_CIPHER_ALGORITHM2_VARIABLE_NONCE_INCLUDED_IN_RECORD,
128,
128,
},
@@ -1701,7 +1701,7 @@
SSL_AEAD,
SSL_TLSV1_2,
SSL_NOT_EXP|SSL_HIGH|SSL_FIPS,
- SSL_HANDSHAKE_MAC_SHA256|TLS1_PRF_SHA256|SSL_CIPHER_ALGORITHM2_AEAD|FIXED_NONCE_LEN(4),
+ SSL_HANDSHAKE_MAC_SHA256|TLS1_PRF_SHA256|SSL_CIPHER_ALGORITHM2_AEAD|FIXED_NONCE_LEN(4)|SSL_CIPHER_ALGORITHM2_VARIABLE_NONCE_INCLUDED_IN_RECORD,
128,
128,
},
@@ -1733,7 +1733,7 @@
SSL_AEAD,
SSL_TLSV1_2,
SSL_NOT_EXP|SSL_HIGH|SSL_FIPS,
- SSL_HANDSHAKE_MAC_SHA256|TLS1_PRF_SHA256|SSL_CIPHER_ALGORITHM2_AEAD|FIXED_NONCE_LEN(4),
+ SSL_HANDSHAKE_MAC_SHA256|TLS1_PRF_SHA256|SSL_CIPHER_ALGORITHM2_AEAD|FIXED_NONCE_LEN(4)|SSL_CIPHER_ALGORITHM2_VARIABLE_NONCE_INCLUDED_IN_RECORD,
128,
128,
},
@@ -1765,7 +1765,7 @@
SSL_AEAD,
SSL_TLSV1_2,
SSL_NOT_EXP|SSL_HIGH|SSL_FIPS,
- SSL_HANDSHAKE_MAC_SHA256|TLS1_PRF_SHA256|SSL_CIPHER_ALGORITHM2_AEAD|FIXED_NONCE_LEN(4),
+ SSL_HANDSHAKE_MAC_SHA256|TLS1_PRF_SHA256|SSL_CIPHER_ALGORITHM2_AEAD|FIXED_NONCE_LEN(4)|SSL_CIPHER_ALGORITHM2_VARIABLE_NONCE_INCLUDED_IN_RECORD,
128,
128,
},
@@ -2349,7 +2349,7 @@
SSL_AEAD,
SSL_TLSV1_2,
SSL_NOT_EXP|SSL_HIGH|SSL_FIPS,
- SSL_HANDSHAKE_MAC_SHA256|TLS1_PRF_SHA256|SSL_CIPHER_ALGORITHM2_AEAD|FIXED_NONCE_LEN(4),
+ SSL_HANDSHAKE_MAC_SHA256|TLS1_PRF_SHA256|SSL_CIPHER_ALGORITHM2_AEAD|FIXED_NONCE_LEN(4)|SSL_CIPHER_ALGORITHM2_VARIABLE_NONCE_INCLUDED_IN_RECORD,
128,
128,
},
@@ -2381,7 +2381,7 @@
SSL_AEAD,
SSL_TLSV1_2,
SSL_NOT_EXP|SSL_HIGH|SSL_FIPS,
- SSL_HANDSHAKE_MAC_SHA256|TLS1_PRF_SHA256|SSL_CIPHER_ALGORITHM2_AEAD|FIXED_NONCE_LEN(4),
+ SSL_HANDSHAKE_MAC_SHA256|TLS1_PRF_SHA256|SSL_CIPHER_ALGORITHM2_AEAD|FIXED_NONCE_LEN(4)|SSL_CIPHER_ALGORITHM2_VARIABLE_NONCE_INCLUDED_IN_RECORD,
128,
128,
},
@@ -2413,7 +2413,7 @@
SSL_AEAD,
SSL_TLSV1_2,
SSL_NOT_EXP|SSL_HIGH|SSL_FIPS,
- SSL_HANDSHAKE_MAC_SHA256|TLS1_PRF_SHA256|SSL_CIPHER_ALGORITHM2_AEAD|FIXED_NONCE_LEN(4),
+ SSL_HANDSHAKE_MAC_SHA256|TLS1_PRF_SHA256|SSL_CIPHER_ALGORITHM2_AEAD|FIXED_NONCE_LEN(4)|SSL_CIPHER_ALGORITHM2_VARIABLE_NONCE_INCLUDED_IN_RECORD,
128,
128,
},
@@ -2445,7 +2445,7 @@
SSL_AEAD,
SSL_TLSV1_2,
SSL_NOT_EXP|SSL_HIGH|SSL_FIPS,
- SSL_HANDSHAKE_MAC_SHA256|TLS1_PRF_SHA256|SSL_CIPHER_ALGORITHM2_AEAD|FIXED_NONCE_LEN(4),
+ SSL_HANDSHAKE_MAC_SHA256|TLS1_PRF_SHA256|SSL_CIPHER_ALGORITHM2_AEAD|FIXED_NONCE_LEN(4)|SSL_CIPHER_ALGORITHM2_VARIABLE_NONCE_INCLUDED_IN_RECORD,
128,
128,
},
@@ -2529,6 +2529,51 @@
},
#endif
+ {
+ 1,
+ TLS1_TXT_ECDHE_RSA_WITH_CHACHA20_POLY1305,
+ TLS1_CK_ECDHE_RSA_CHACHA20_POLY1305,
+ SSL_kEECDH,
+ SSL_aRSA,
+ SSL_CHACHA20POLY1305,
+ SSL_AEAD,
+ SSL_TLSV1_2,
+ SSL_NOT_EXP|SSL_HIGH,
+ SSL_HANDSHAKE_MAC_SHA256|TLS1_PRF_SHA256|SSL_CIPHER_ALGORITHM2_AEAD|FIXED_NONCE_LEN(0),
+ 256,
+ 0,
+ },
+
+ {
+ 1,
+ TLS1_TXT_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,
+ TLS1_CK_ECDHE_ECDSA_CHACHA20_POLY1305,
+ SSL_kEECDH,
+ SSL_aECDSA,
+ SSL_CHACHA20POLY1305,
+ SSL_AEAD,
+ SSL_TLSV1_2,
+ SSL_NOT_EXP|SSL_HIGH,
+ SSL_HANDSHAKE_MAC_SHA256|TLS1_PRF_SHA256|SSL_CIPHER_ALGORITHM2_AEAD|FIXED_NONCE_LEN(0),
+ 256,
+ 0,
+ },
+
+ {
+ 1,
+ TLS1_TXT_DHE_RSA_WITH_CHACHA20_POLY1305,
+ TLS1_CK_DHE_RSA_CHACHA20_POLY1305,
+ SSL_kEDH,
+ SSL_aRSA,
+ SSL_CHACHA20POLY1305,
+ SSL_AEAD,
+ SSL_TLSV1_2,
+ SSL_NOT_EXP|SSL_HIGH,
+ SSL_HANDSHAKE_MAC_SHA256|TLS1_PRF_SHA256|SSL_CIPHER_ALGORITHM2_AEAD|FIXED_NONCE_LEN(0),
+ 256,
+ 0,
+ },
+
/* end of list */
};
diff --git a/ssl/s3_pkt.c b/ssl/s3_pkt.c
index c244724..563f96e 100644
--- a/ssl/s3_pkt.c
+++ b/ssl/s3_pkt.c
@@ -765,8 +765,11 @@
else
eivlen = 0;
}
- else if (s->aead_write_ctx != NULL)
+ else if (s->aead_write_ctx != NULL &&
+ s->aead_write_ctx->variable_nonce_included_in_record)
+ {
eivlen = s->aead_write_ctx->variable_nonce_len;
+ }
else
eivlen = 0;
diff --git a/ssl/ssl.h b/ssl/ssl.h
index 5c0626c..bf978a0 100644
--- a/ssl/ssl.h
+++ b/ssl/ssl.h
@@ -281,6 +281,7 @@
#define SSL_TXT_CAMELLIA128 "CAMELLIA128"
#define SSL_TXT_CAMELLIA256 "CAMELLIA256"
#define SSL_TXT_CAMELLIA "CAMELLIA"
+#define SSL_TXT_CHACHA20 "CHACHA20"
#define SSL_TXT_MD5 "MD5"
#define SSL_TXT_SHA1 "SHA1"
@@ -2258,6 +2259,7 @@
int SSL_CIPHER_is_AES(const SSL_CIPHER *c);
int SSL_CIPHER_has_MD5_HMAC(const SSL_CIPHER *c);
int SSL_CIPHER_is_AESGCM(const SSL_CIPHER *c);
+int SSL_CIPHER_is_CHACHA20POLY1305(const SSL_CIPHER *c);
/* This sets the 'default' SSL version that SSL_new() will create */
int SSL_CTX_set_ssl_version(SSL_CTX *ctx, const SSL_METHOD *meth);
diff --git a/ssl/ssl_ciph.c b/ssl/ssl_ciph.c
index e235020..2cee44c 100644
--- a/ssl/ssl_ciph.c
+++ b/ssl/ssl_ciph.c
@@ -296,6 +296,7 @@
{0,SSL_TXT_CAMELLIA128,0,0,0,SSL_CAMELLIA128,0,0,0,0,0,0},
{0,SSL_TXT_CAMELLIA256,0,0,0,SSL_CAMELLIA256,0,0,0,0,0,0},
{0,SSL_TXT_CAMELLIA ,0,0,0,SSL_CAMELLIA128|SSL_CAMELLIA256,0,0,0,0,0,0},
+ {0,SSL_TXT_CHACHA20 ,0,0,0,SSL_CHACHA20POLY1305,0,0,0,0,0,0},
/* MAC aliases */
{0,SSL_TXT_MD5,0, 0,0,0,SSL_MD5, 0,0,0,0,0},
@@ -385,9 +386,15 @@
return 0;
#ifndef OPENSSL_NO_AES
- /* There is only one AEAD for now. */
- *aead = EVP_aead_aes_128_gcm();
- return 1;
+ switch (c->algorithm_enc)
+ {
+ case SSL_AES128GCM:
+ *aead = EVP_aead_aes_128_gcm();
+ return 1;
+ case SSL_CHACHA20POLY1305:
+ *aead = EVP_aead_chacha20_poly1305();
+ return 1;
+ }
#endif
return 0;
@@ -1621,6 +1628,9 @@
case SSL_SEED:
enc="SEED(128)";
break;
+ case SSL_CHACHA20POLY1305:
+ enc="ChaCha20-Poly1305";
+ break;
default:
enc="unknown";
break;
@@ -1681,6 +1691,11 @@
return (c->algorithm_mac & (SSL_AES128GCM|SSL_AES256GCM)) != 0;
}
+int SSL_CIPHER_is_CHACHA20POLY1305(const SSL_CIPHER *c)
+ {
+ return (c->algorithm_enc & SSL_CHACHA20POLY1305) != 0;
+ }
+
char *SSL_CIPHER_get_version(const SSL_CIPHER *c)
{
int i;
diff --git a/ssl/ssl_locl.h b/ssl/ssl_locl.h
index 22637a1..ed25099 100644
--- a/ssl/ssl_locl.h
+++ b/ssl/ssl_locl.h
@@ -316,6 +316,7 @@
#define SSL_SEED 0x00000800L
#define SSL_AES128GCM 0x00001000L
#define SSL_AES256GCM 0x00002000L
+#define SSL_CHACHA20POLY1305 0x00004000L
#define SSL_AES (SSL_AES128|SSL_AES256|SSL_AES128GCM|SSL_AES256GCM)
#define SSL_CAMELLIA (SSL_CAMELLIA128|SSL_CAMELLIA256)
@@ -377,6 +378,12 @@
#define SSL_CIPHER_AEAD_FIXED_NONCE_LEN(ssl_cipher) \
(((ssl_cipher->algorithm2 >> 24) & 0xf)*2)
+/* SSL_CIPHER_ALGORITHM2_VARIABLE_NONCE_INCLUDED_IN_RECORD is a flag in
+ * SSL_CIPHER.algorithm2 which indicates that the variable part of the nonce is
+ * included as a prefix of the record. (AES-GCM, for example, does with with an
+ * 8-byte variable nonce.) */
+#define SSL_CIPHER_ALGORITHM2_VARIABLE_NONCE_INCLUDED_IN_RECORD (1<<22)
+
/*
* Export and cipher strength information. For each cipher we have to decide
* whether it is exportable or not. This information is likely to change
@@ -747,6 +754,9 @@
* records. */
unsigned char fixed_nonce[8];
unsigned char fixed_nonce_len, variable_nonce_len, tag_len;
+ /* variable_nonce_included_in_record is non-zero if the variable nonce
+ * for a record is included as a prefix before the ciphertext. */
+ char variable_nonce_included_in_record;
};
#ifndef OPENSSL_NO_COMP
diff --git a/ssl/t1_enc.c b/ssl/t1_enc.c
index 58f8bf8..7897519 100644
--- a/ssl/t1_enc.c
+++ b/ssl/t1_enc.c
@@ -361,6 +361,8 @@
memcpy(aead_ctx->fixed_nonce, iv, iv_len);
aead_ctx->fixed_nonce_len = iv_len;
aead_ctx->variable_nonce_len = 8; /* always the case, currently. */
+ aead_ctx->variable_nonce_included_in_record =
+ (s->s3->tmp.new_cipher->algorithm2 & SSL_CIPHER_ALGORITHM2_VARIABLE_NONCE_INCLUDED_IN_RECORD) != 0;
if (aead_ctx->variable_nonce_len + aead_ctx->fixed_nonce_len != EVP_AEAD_nonce_length(aead))
{
OPENSSL_PUT_ERROR(SSL, tls1_change_cipher_state_aead, ERR_R_INTERNAL_ERROR);
@@ -822,6 +824,7 @@
if (send)
{
size_t len = rec->length;
+ size_t eivlen = 0;
in = rec->input;
out = rec->data;
@@ -837,22 +840,27 @@
* variable nonce. Thus we can copy the sequence number
* bytes into place without overwriting any of the
* plaintext. */
- memcpy(out, ad, aead->variable_nonce_len);
- len -= aead->variable_nonce_len;
+ if (aead->variable_nonce_included_in_record)
+ {
+ memcpy(out, ad, aead->variable_nonce_len);
+ len -= aead->variable_nonce_len;
+ eivlen = aead->variable_nonce_len;
+ }
ad[11] = len >> 8;
ad[12] = len & 0xff;
if (!EVP_AEAD_CTX_seal(
&aead->ctx,
- out + aead->variable_nonce_len, &n, len + aead->tag_len,
+ out + eivlen, &n, len + aead->tag_len,
nonce, nonce_used,
- in + aead->variable_nonce_len, len,
+ in + eivlen, len,
ad, sizeof(ad)))
{
return -1;
}
- n += aead->variable_nonce_len;
+ if (aead->variable_nonce_included_in_record)
+ n += aead->variable_nonce_len;
}
else
{
@@ -865,12 +873,17 @@
if (len < aead->variable_nonce_len)
return 0;
- memcpy(nonce + nonce_used, in, aead->variable_nonce_len);
+ memcpy(nonce + nonce_used,
+ aead->variable_nonce_included_in_record ? in : ad,
+ aead->variable_nonce_len);
nonce_used += aead->variable_nonce_len;
- in += aead->variable_nonce_len;
- len -= aead->variable_nonce_len;
- out += aead->variable_nonce_len;
+ if (aead->variable_nonce_included_in_record)
+ {
+ in += aead->variable_nonce_len;
+ len -= aead->variable_nonce_len;
+ out += aead->variable_nonce_len;
+ }
if (len < aead->tag_len)
return 0;
diff --git a/ssl/tls1.h b/ssl/tls1.h
index 75de4c4..d09a6e3 100644
--- a/ssl/tls1.h
+++ b/ssl/tls1.h
@@ -567,6 +567,10 @@
#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 0x0300CC13
+#define TLS1_CK_ECDHE_ECDSA_CHACHA20_POLY1305 0x0300CC14
+#define TLS1_CK_DHE_RSA_CHACHA20_POLY1305 0x0300CC15
+
/* XXX
* Inconsistency alert:
* The OpenSSL names of ciphers with ephemeral DH here include the string
@@ -718,6 +722,10 @@
#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"
+#define TLS1_TXT_ECDHE_RSA_WITH_CHACHA20_POLY1305 "ECDHE-RSA-CHACHA20-POLY1305"
+#define TLS1_TXT_ECDHE_ECDSA_WITH_CHACHA20_POLY1305 "ECDHE-ECDSA-CHACHA20-POLY1305"
+#define TLS1_TXT_DHE_RSA_WITH_CHACHA20_POLY1305 "DHE-RSA-CHACHA20-POLY1305"
+
#define TLS_CT_RSA_SIGN 1
#define TLS_CT_DSS_SIGN 2
#define TLS_CT_RSA_FIXED_DH 3