summaryrefslogtreecommitdiff
path: root/openssl/ssl
diff options
context:
space:
mode:
authoragl@chromium.org <agl@chromium.org@4ff67af0-8c30-449e-8e8b-ad334ec8d88c>2013-11-06 21:17:55 +0000
committeragl@chromium.org <agl@chromium.org@4ff67af0-8c30-449e-8e8b-ad334ec8d88c>2013-11-06 21:17:55 +0000
commit219af2cde3d824e82b72b3efc070f3a14fbe3c10 (patch)
tree8788214bdc66e5e489ed65e213a2b5c5d1507a6f /openssl/ssl
parentcf2eb320f09318966c9ae11c565615a16b453fff (diff)
downloadopenssl-219af2cde3d824e82b72b3efc070f3a14fbe3c10.tar.gz
third_party/openssl: add ChaCha20+Poly1305 support.
This change is not as scary as it appears. Most of the code has already been reviewed and is running in production without issues. The only new code is the ARM support. ARM now builds both the NEON and generic versions of the code and can enable the NEON code at runtime by calling CRYPTO_set_NEON_capable(1). This patch does not contain the code to call that, however. The addition openssl/patches/channelidchromium.patch and fix_lhash_iteration.patch is noise from the import script. BUG=310768 https://codereview.chromium.org/59083010/ git-svn-id: http://src.chromium.org/svn/trunk/deps/third_party/openssl@233370 4ff67af0-8c30-449e-8e8b-ad334ec8d88c
Diffstat (limited to 'openssl/ssl')
-rw-r--r--openssl/ssl/s2_clnt.c2
-rw-r--r--openssl/ssl/s2_enc.c2
-rw-r--r--openssl/ssl/s2_srvr.c2
-rw-r--r--openssl/ssl/s3_enc.c8
-rw-r--r--openssl/ssl/s3_lib.c80
-rw-r--r--openssl/ssl/s3_pkt.c7
-rw-r--r--openssl/ssl/ssl.h17
-rw-r--r--openssl/ssl/ssl3.h1
-rw-r--r--openssl/ssl/ssl_ciph.c80
-rw-r--r--openssl/ssl/ssl_err.c5
-rw-r--r--openssl/ssl/ssl_lib.c12
-rw-r--r--openssl/ssl/ssl_locl.h33
-rw-r--r--openssl/ssl/ssl_txt.c2
-rw-r--r--openssl/ssl/t1_enc.c645
-rw-r--r--openssl/ssl/tls1.h8
15 files changed, 673 insertions, 231 deletions
diff --git a/openssl/ssl/s2_clnt.c b/openssl/ssl/s2_clnt.c
index 03b6cf9..32adaf5 100644
--- a/openssl/ssl/s2_clnt.c
+++ b/openssl/ssl/s2_clnt.c
@@ -623,7 +623,7 @@ static int client_master_key(SSL *s)
if (s->state == SSL2_ST_SEND_CLIENT_MASTER_KEY_A)
{
- if (!ssl_cipher_get_evp(s->session,&c,&md,NULL,NULL,NULL))
+ if (!ssl_cipher_get_evp(s->session,&c,&md,NULL,NULL))
{
ssl2_return_error(s,SSL2_PE_NO_CIPHER);
SSLerr(SSL_F_CLIENT_MASTER_KEY,SSL_R_PROBLEMS_MAPPING_CIPHER_FUNCTIONS);
diff --git a/openssl/ssl/s2_enc.c b/openssl/ssl/s2_enc.c
index ff3395f..087c4a2 100644
--- a/openssl/ssl/s2_enc.c
+++ b/openssl/ssl/s2_enc.c
@@ -68,7 +68,7 @@ int ssl2_enc_init(SSL *s, int client)
const EVP_MD *md;
int num;
- if (!ssl_cipher_get_evp(s->session,&c,&md,NULL,NULL,NULL))
+ if (!ssl_cipher_get_evp(s->session,&c,&md,NULL,NULL))
{
ssl2_return_error(s,SSL2_PE_NO_CIPHER);
SSLerr(SSL_F_SSL2_ENC_INIT,SSL_R_PROBLEMS_MAPPING_CIPHER_FUNCTIONS);
diff --git a/openssl/ssl/s2_srvr.c b/openssl/ssl/s2_srvr.c
index 2cba426..3b14faa 100644
--- a/openssl/ssl/s2_srvr.c
+++ b/openssl/ssl/s2_srvr.c
@@ -452,7 +452,7 @@ static int get_client_master_key(SSL *s)
is_export=SSL_C_IS_EXPORT(s->session->cipher);
- if (!ssl_cipher_get_evp(s->session,&c,&md,NULL,NULL,NULL))
+ if (!ssl_cipher_get_evp(s->session,&c,&md,NULL,NULL))
{
ssl2_return_error(s,SSL2_PE_NO_CIPHER);
SSLerr(SSL_F_GET_CLIENT_MASTER_KEY,SSL_R_PROBLEMS_MAPPING_CIPHER_FUNCTIONS);
diff --git a/openssl/ssl/s3_enc.c b/openssl/ssl/s3_enc.c
index e3cd4f0..191b86b 100644
--- a/openssl/ssl/s3_enc.c
+++ b/openssl/ssl/s3_enc.c
@@ -397,7 +397,13 @@ int ssl3_setup_key_block(SSL *s)
if (s->s3->tmp.key_block_length != 0)
return(1);
- if (!ssl_cipher_get_evp(s->session,&c,&hash,NULL,NULL,&comp))
+ if (!ssl_cipher_get_comp(s->session, &comp))
+ {
+ SSLerr(SSL_F_SSL3_SETUP_KEY_BLOCK,SSL_R_CIPHER_OR_HASH_UNAVAILABLE);
+ return(0);
+ }
+
+ if (!ssl_cipher_get_evp(s->session,&c,&hash,NULL,NULL))
{
SSLerr(SSL_F_SSL3_SETUP_KEY_BLOCK,SSL_R_CIPHER_OR_HASH_UNAVAILABLE);
return(0);
diff --git a/openssl/ssl/s3_lib.c b/openssl/ssl/s3_lib.c
index a71d05a..605979b 100644
--- a/openssl/ssl/s3_lib.c
+++ b/openssl/ssl/s3_lib.c
@@ -166,6 +166,11 @@ const char ssl3_version_str[]="SSLv3" OPENSSL_VERSION_PTEXT;
#define SSL3_NUM_CIPHERS (sizeof(ssl3_ciphers)/sizeof(SSL_CIPHER))
+/* FIXED_NONCE_LEN is a macro that results in the correct value to set the
+ * fixed nonce length in SSL_CIPHER.algorithms2. It's the inverse of
+ * SSL_CIPHER_AEAD_FIXED_NONCE_LEN. */
+#define FIXED_NONCE_LEN(x) ((x/2)<<24)
+
/* list of available SSLv3 ciphers (sorted by id) */
OPENSSL_GLOBAL SSL_CIPHER ssl3_ciphers[]={
@@ -1836,7 +1841,8 @@ OPENSSL_GLOBAL SSL_CIPHER ssl3_ciphers[]={
SSL_AEAD,
SSL_TLSV1_2,
SSL_NOT_EXP|SSL_HIGH|SSL_FIPS,
- SSL_HANDSHAKE_MAC_SHA256|TLS1_PRF_SHA256,
+ 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,
},
@@ -1868,7 +1874,8 @@ OPENSSL_GLOBAL SSL_CIPHER ssl3_ciphers[]={
SSL_AEAD,
SSL_TLSV1_2,
SSL_NOT_EXP|SSL_HIGH|SSL_FIPS,
- SSL_HANDSHAKE_MAC_SHA256|TLS1_PRF_SHA256,
+ 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,
},
@@ -1900,7 +1907,8 @@ OPENSSL_GLOBAL SSL_CIPHER ssl3_ciphers[]={
SSL_AEAD,
SSL_TLSV1_2,
SSL_NOT_EXP|SSL_HIGH|SSL_FIPS,
- SSL_HANDSHAKE_MAC_SHA256|TLS1_PRF_SHA256,
+ 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,
},
@@ -1932,7 +1940,8 @@ OPENSSL_GLOBAL SSL_CIPHER ssl3_ciphers[]={
SSL_AEAD,
SSL_TLSV1_2,
SSL_NOT_EXP|SSL_HIGH|SSL_FIPS,
- SSL_HANDSHAKE_MAC_SHA256|TLS1_PRF_SHA256,
+ 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,
},
@@ -1964,7 +1973,8 @@ OPENSSL_GLOBAL SSL_CIPHER ssl3_ciphers[]={
SSL_AEAD,
SSL_TLSV1_2,
SSL_NOT_EXP|SSL_HIGH|SSL_FIPS,
- SSL_HANDSHAKE_MAC_SHA256|TLS1_PRF_SHA256,
+ 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,
},
@@ -1996,7 +2006,8 @@ OPENSSL_GLOBAL SSL_CIPHER ssl3_ciphers[]={
SSL_AEAD,
SSL_TLSV1_2,
SSL_NOT_EXP|SSL_HIGH|SSL_FIPS,
- SSL_HANDSHAKE_MAC_SHA256|TLS1_PRF_SHA256,
+ 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,
},
@@ -2709,7 +2720,8 @@ OPENSSL_GLOBAL SSL_CIPHER ssl3_ciphers[]={
SSL_AEAD,
SSL_TLSV1_2,
SSL_NOT_EXP|SSL_HIGH|SSL_FIPS,
- SSL_HANDSHAKE_MAC_SHA256|TLS1_PRF_SHA256,
+ 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,
},
@@ -2741,7 +2753,8 @@ OPENSSL_GLOBAL SSL_CIPHER ssl3_ciphers[]={
SSL_AEAD,
SSL_TLSV1_2,
SSL_NOT_EXP|SSL_HIGH|SSL_FIPS,
- SSL_HANDSHAKE_MAC_SHA256|TLS1_PRF_SHA256,
+ 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,
},
@@ -2773,7 +2786,8 @@ OPENSSL_GLOBAL SSL_CIPHER ssl3_ciphers[]={
SSL_AEAD,
SSL_TLSV1_2,
SSL_NOT_EXP|SSL_HIGH|SSL_FIPS,
- SSL_HANDSHAKE_MAC_SHA256|TLS1_PRF_SHA256,
+ 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,
},
@@ -2805,7 +2819,8 @@ OPENSSL_GLOBAL SSL_CIPHER ssl3_ciphers[]={
SSL_AEAD,
SSL_TLSV1_2,
SSL_NOT_EXP|SSL_HIGH|SSL_FIPS,
- SSL_HANDSHAKE_MAC_SHA256|TLS1_PRF_SHA256,
+ 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,
},
@@ -2889,6 +2904,51 @@ OPENSSL_GLOBAL SSL_CIPHER ssl3_ciphers[]={
},
#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/openssl/ssl/s3_pkt.c b/openssl/ssl/s3_pkt.c
index 804291e..9f117d1 100644
--- a/openssl/ssl/s3_pkt.c
+++ b/openssl/ssl/s3_pkt.c
@@ -773,7 +773,12 @@ static int do_ssl3_write(SSL *s, int type, const unsigned char *buf,
else
eivlen = 0;
}
- else
+ 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;
/* lets setup the record stuff. */
diff --git a/openssl/ssl/ssl.h b/openssl/ssl/ssl.h
index 2853a91..a3944f1 100644
--- a/openssl/ssl/ssl.h
+++ b/openssl/ssl/ssl.h
@@ -291,6 +291,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_MD5 "MD5"
#define SSL_TXT_SHA1 "SHA1"
@@ -399,7 +400,9 @@ struct ssl_cipher_st
unsigned long algorithm_ssl; /* (major) protocol version */
unsigned long algo_strength; /* strength and export flags */
- unsigned long algorithm2; /* Extra flags */
+ unsigned long algorithm2; /* Extra flags. See SSL2_CF_* in ssl2.h
+ and algorithm2 section in
+ ssl_locl.h */
int strength_bits; /* Number of bits really used */
int alg_bits; /* Number of bits for algorithm */
};
@@ -728,6 +731,9 @@ int SRP_generate_client_master_secret(SSL *s,unsigned char *master_key);
#endif
+struct ssl_aead_ctx_st;
+typedef struct ssl_aead_ctx_st SSL_AEAD_CTX;
+
#if defined(OPENSSL_SYS_MSDOS) && !defined(OPENSSL_SYS_WIN32)
#define SSL_MAX_CERT_LIST_DEFAULT 1024*30 /* 30k max cert list :-) */
#else
@@ -1213,6 +1219,9 @@ struct ssl_st
/* These are the ones being used, the ones in SSL_SESSION are
* the ones to be 'copied' into these ones */
int mac_flags;
+ SSL_AEAD_CTX *aead_read_ctx; /* AEAD context. If non-NULL, then
+ |enc_read_ctx| and |read_hash| are
+ ignored. */
EVP_CIPHER_CTX *enc_read_ctx; /* cryptographic state */
EVP_MD_CTX *read_hash; /* used for mac generation */
#ifndef OPENSSL_NO_COMP
@@ -1221,6 +1230,9 @@ struct ssl_st
char *expand;
#endif
+ SSL_AEAD_CTX *aead_write_ctx; /* AEAD context. If non-NULL, then
+ |enc_write_ctx| and |write_hash| are
+ ignored. */
EVP_CIPHER_CTX *enc_write_ctx; /* cryptographic state */
EVP_MD_CTX *write_hash; /* used for mac generation */
#ifndef OPENSSL_NO_COMP
@@ -2327,8 +2339,11 @@ void ERR_load_SSL_strings(void);
#define SSL_F_SSL_USE_RSAPRIVATEKEY_FILE 206
#define SSL_F_SSL_VERIFY_CERT_CHAIN 207
#define SSL_F_SSL_WRITE 208
+#define SSL_F_TLS1_AEAD_CTX_INIT 339
#define SSL_F_TLS1_CERT_VERIFY_MAC 286
#define SSL_F_TLS1_CHANGE_CIPHER_STATE 209
+#define SSL_F_TLS1_CHANGE_CIPHER_STATE_AEAD 340
+#define SSL_F_TLS1_CHANGE_CIPHER_STATE_CIPHER 338
#define SSL_F_TLS1_CHECK_SERVERHELLO_TLSEXT 274
#define SSL_F_TLS1_ENC 210
#define SSL_F_TLS1_EXPORT_KEYING_MATERIAL 314
diff --git a/openssl/ssl/ssl3.h b/openssl/ssl/ssl3.h
index fee9671..899c8a8 100644
--- a/openssl/ssl/ssl3.h
+++ b/openssl/ssl/ssl3.h
@@ -517,6 +517,7 @@ typedef struct ssl3_state_st
unsigned char *key_block;
const EVP_CIPHER *new_sym_enc;
+ const EVP_AEAD *new_aead;
const EVP_MD *new_hash;
int new_mac_pkey_type;
int new_mac_secret_size;
diff --git a/openssl/ssl/ssl_ciph.c b/openssl/ssl/ssl_ciph.c
index e8794d4..db85b29 100644
--- a/openssl/ssl/ssl_ciph.c
+++ b/openssl/ssl/ssl_ciph.c
@@ -298,6 +298,7 @@ static const SSL_CIPHER cipher_aliases[]={
{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},
@@ -484,32 +485,72 @@ static void load_builtin_compressions(void)
}
#endif
+/* ssl_cipher_get_comp sets |comp| to the correct SSL_COMP for the given
+ * session and returns 1. On error it returns 0. */
+int ssl_cipher_get_comp(const SSL_SESSION *s, SSL_COMP **comp)
+ {
+ int i;
+
+ SSL_COMP ctmp;
+#ifndef OPENSSL_NO_COMP
+ load_builtin_compressions();
+#endif
+
+ *comp=NULL;
+ ctmp.id=s->compress_meth;
+ if (ssl_comp_methods != NULL)
+ {
+ i=sk_SSL_COMP_find(ssl_comp_methods,&ctmp);
+ if (i >= 0)
+ *comp=sk_SSL_COMP_value(ssl_comp_methods,i);
+ else
+ *comp=NULL;
+ }
+
+ return 1;
+ }
+
+/* ssl_cipher_get_evp_aead sets |*aead| to point to the correct EVP_AEAD object
+ * for |s->cipher|. It returns 1 on success and 0 on error. */
+int ssl_cipher_get_evp_aead(const SSL_SESSION *s, const EVP_AEAD **aead)
+ {
+ const SSL_CIPHER *c = s->cipher;
+
+ *aead = NULL;
+
+ if (c == NULL)
+ return 0;
+ if ((c->algorithm2 & SSL_CIPHER_ALGORITHM2_AEAD) == 0)
+ return 0;
+
+#ifndef OPENSSL_NO_AES
+ 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;
+ }
+
int ssl_cipher_get_evp(const SSL_SESSION *s, const EVP_CIPHER **enc,
- const EVP_MD **md, int *mac_pkey_type, int *mac_secret_size,SSL_COMP **comp)
+ const EVP_MD **md, int *mac_pkey_type, int *mac_secret_size)
{
int i;
const SSL_CIPHER *c;
c=s->cipher;
if (c == NULL) return(0);
- if (comp != NULL)
- {
- SSL_COMP ctmp;
-#ifndef OPENSSL_NO_COMP
- load_builtin_compressions();
-#endif
- *comp=NULL;
- ctmp.id=s->compress_meth;
- if (ssl_comp_methods != NULL)
- {
- i=sk_SSL_COMP_find(ssl_comp_methods,&ctmp);
- if (i >= 0)
- *comp=sk_SSL_COMP_value(ssl_comp_methods,i);
- else
- *comp=NULL;
- }
- }
+ /* This function doesn't deal with EVP_AEAD. See
+ * |ssl_cipher_get_aead_evp|. */
+ if (c->algorithm2 & SSL_CIPHER_ALGORITHM2_AEAD)
+ return(0);
if ((enc == NULL) || (md == NULL)) return(0);
@@ -1675,6 +1716,9 @@ char *SSL_CIPHER_description(const SSL_CIPHER *cipher, char *buf, int len)
case SSL_SEED:
enc="SEED(128)";
break;
+ case SSL_CHACHA20POLY1305:
+ enc="ChaCha20-Poly1305";
+ break;
default:
enc="unknown";
break;
diff --git a/openssl/ssl/ssl_err.c b/openssl/ssl/ssl_err.c
index c40c718..c29391c 100644
--- a/openssl/ssl/ssl_err.c
+++ b/openssl/ssl/ssl_err.c
@@ -280,7 +280,10 @@ static ERR_STRING_DATA SSL_str_functs[]=
{ERR_FUNC(SSL_F_SSL_VERIFY_CERT_CHAIN), "SSL_VERIFY_CERT_CHAIN"},
{ERR_FUNC(SSL_F_SSL_WRITE), "SSL_write"},
{ERR_FUNC(SSL_F_TLS1_CERT_VERIFY_MAC), "tls1_cert_verify_mac"},
-{ERR_FUNC(SSL_F_TLS1_CHANGE_CIPHER_STATE), "TLS1_CHANGE_CIPHER_STATE"},
+{ERR_FUNC(SSL_F_TLS1_AEAD_CTX_INIT), "TLS1_AEAD_CTX_INIT"},
+{ERR_FUNC(SSL_F_TLS1_CHANGE_CIPHER_STATE), "tls1_change_cipher_state"},
+{ERR_FUNC(SSL_F_TLS1_CHANGE_CIPHER_STATE_AEAD), "TLS1_CHANGE_CIPHER_STATE_AEAD"},
+{ERR_FUNC(SSL_F_TLS1_CHANGE_CIPHER_STATE_CIPHER), "TLS1_CHANGE_CIPHER_STATE_CIPHER"},
{ERR_FUNC(SSL_F_TLS1_CHECK_SERVERHELLO_TLSEXT), "TLS1_CHECK_SERVERHELLO_TLSEXT"},
{ERR_FUNC(SSL_F_TLS1_ENC), "TLS1_ENC"},
{ERR_FUNC(SSL_F_TLS1_EXPORT_KEYING_MATERIAL), "TLS1_EXPORT_KEYING_MATERIAL"},
diff --git a/openssl/ssl/ssl_lib.c b/openssl/ssl/ssl_lib.c
index 92e2cf3..45a76ae 100644
--- a/openssl/ssl/ssl_lib.c
+++ b/openssl/ssl/ssl_lib.c
@@ -2836,6 +2836,18 @@ void ssl_clear_cipher_ctx(SSL *s)
OPENSSL_free(s->enc_write_ctx);
s->enc_write_ctx=NULL;
}
+ if (s->aead_read_ctx != NULL)
+ {
+ EVP_AEAD_CTX_cleanup(&s->aead_read_ctx->ctx);
+ OPENSSL_free(s->aead_read_ctx);
+ s->aead_read_ctx = NULL;
+ }
+ if (s->aead_write_ctx != NULL)
+ {
+ EVP_AEAD_CTX_cleanup(&s->aead_write_ctx->ctx);
+ OPENSSL_free(s->aead_write_ctx);
+ s->aead_write_ctx = NULL;
+ }
#ifndef OPENSSL_NO_COMP
if (s->expand != NULL)
{
diff --git a/openssl/ssl/ssl_locl.h b/openssl/ssl/ssl_locl.h
index 5f21726..2f8cda8 100644
--- a/openssl/ssl/ssl_locl.h
+++ b/openssl/ssl/ssl_locl.h
@@ -328,6 +328,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)
@@ -380,6 +381,20 @@
#define TLSEXT_CHANNEL_ID_SIZE 128
+/* SSL_CIPHER_ALGORITHM2_AEAD is a flag in SSL_CIPHER.algorithm2 which
+ * indicates that the cipher is implemented via an EVP_AEAD. */
+#define SSL_CIPHER_ALGORITHM2_AEAD (1<<23)
+
+/* SSL_CIPHER_AEAD_FIXED_NONCE_LEN returns the number of bytes of fixed nonce
+ * for an SSL_CIPHER* with the SSL_CIPHER_ALGORITHM2_AEAD flag. */
+#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
@@ -588,6 +603,20 @@ typedef struct ssl3_enc_method
int use_context);
} SSL3_ENC_METHOD;
+/* ssl_aead_ctx_st contains information about an AEAD that is being used to
+ * encrypt an SSL connection. */
+struct ssl_aead_ctx_st
+ {
+ EVP_AEAD_CTX ctx;
+ /* fixed_nonce contains any bytes of the nonce that are fixed for all
+ * 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
/* Used for holding the relevant compression methods loaded into SSL_CTX */
typedef struct ssl3_comp_st
@@ -834,8 +863,10 @@ STACK_OF(SSL_CIPHER) *ssl_create_cipher_list(const SSL_METHOD *meth,
STACK_OF(SSL_CIPHER) **sorted,
const char *rule_str);
void ssl_update_cache(SSL *s, int mode);
+int ssl_cipher_get_comp(const SSL_SESSION *s, SSL_COMP **comp);
+int ssl_cipher_get_evp_aead(const SSL_SESSION *s, const EVP_AEAD **aead);
int ssl_cipher_get_evp(const SSL_SESSION *s,const EVP_CIPHER **enc,
- const EVP_MD **md,int *mac_pkey_type,int *mac_secret_size, SSL_COMP **comp);
+ const EVP_MD **md,int *mac_pkey_type,int *mac_secret_size);
int ssl_get_handshake_digest(int i,long *mask,const EVP_MD **md);
int ssl_verify_cert_chain(SSL *s,STACK_OF(X509) *sk);
int ssl_undefined_function(SSL *s);
diff --git a/openssl/ssl/ssl_txt.c b/openssl/ssl/ssl_txt.c
index 6479d52..07826d5 100644
--- a/openssl/ssl/ssl_txt.c
+++ b/openssl/ssl/ssl_txt.c
@@ -216,7 +216,7 @@ int SSL_SESSION_print(BIO *bp, const SSL_SESSION *x)
{
SSL_COMP *comp = NULL;
- ssl_cipher_get_evp(x,NULL,NULL,NULL,NULL,&comp);
+ ssl_cipher_get_comp(x, &comp);
if (comp == NULL)
{
if (BIO_printf(bp,"\n Compression: %d",x->compress_meth) <= 0) goto err;
diff --git a/openssl/ssl/t1_enc.c b/openssl/ssl/t1_enc.c
index 809ad2e..87b7021 100644
--- a/openssl/ssl/t1_enc.c
+++ b/openssl/ssl/t1_enc.c
@@ -316,56 +316,92 @@ static int tls1_generate_key_block(SSL *s, unsigned char *km,
return ret;
}
-int tls1_change_cipher_state(SSL *s, int which)
+/* tls1_aead_ctx_init allocates |*aead_ctx|, if needed and returns 1. It
+ * returns 0 on malloc error. */
+static int tls1_aead_ctx_init(SSL_AEAD_CTX **aead_ctx)
{
- static const unsigned char empty[]="";
- unsigned char *p,*mac_secret;
- unsigned char *exp_label;
- unsigned char tmp1[EVP_MAX_KEY_LENGTH];
- unsigned char tmp2[EVP_MAX_KEY_LENGTH];
- unsigned char iv1[EVP_MAX_IV_LENGTH*2];
- unsigned char iv2[EVP_MAX_IV_LENGTH*2];
- unsigned char *ms,*key,*iv;
- int client_write;
- EVP_CIPHER_CTX *dd;
- const EVP_CIPHER *c;
-#ifndef OPENSSL_NO_COMP
- const SSL_COMP *comp;
-#endif
- const EVP_MD *m;
- int mac_type;
- int *mac_secret_size;
- EVP_MD_CTX *mac_ctx;
- EVP_PKEY *mac_key;
- int is_export,n,i,j,k,exp_label_len,cl;
- int reuse_dd = 0;
+ if (*aead_ctx != NULL)
+ EVP_AEAD_CTX_cleanup(&(*aead_ctx)->ctx);
+ else
+ {
+ *aead_ctx = (SSL_AEAD_CTX*) OPENSSL_malloc(sizeof(SSL_AEAD_CTX));
+ if (*aead_ctx == NULL)
+ {
+ SSLerr(SSL_F_TLS1_AEAD_CTX_INIT, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ }
- is_export=SSL_C_IS_EXPORT(s->s3->tmp.new_cipher);
- c=s->s3->tmp.new_sym_enc;
- m=s->s3->tmp.new_hash;
- mac_type = s->s3->tmp.new_mac_pkey_type;
-#ifndef OPENSSL_NO_COMP
- comp=s->s3->tmp.new_compression;
-#endif
+ return 1;
+ }
-#ifdef KSSL_DEBUG
- printf("tls1_change_cipher_state(which= %d) w/\n", which);
- printf("\talg= %ld/%ld, comp= %p\n",
- s->s3->tmp.new_cipher->algorithm_mkey,
- s->s3->tmp.new_cipher->algorithm_auth,
- comp);
- printf("\tevp_cipher == %p ==? &d_cbc_ede_cipher3\n", c);
- printf("\tevp_cipher: nid, blksz= %d, %d, keylen=%d, ivlen=%d\n",
- c->nid,c->block_size,c->key_len,c->iv_len);
- printf("\tkey_block: len= %d, data= ", s->s3->tmp.key_block_length);
+static int tls1_change_cipher_state_aead(SSL *s, char is_read,
+ const unsigned char *key, unsigned key_len,
+ const unsigned char *iv, unsigned iv_len)
{
- int i;
- for (i=0; i<s->s3->tmp.key_block_length; i++)
- printf("%02x", s->s3->tmp.key_block[i]); printf("\n");
- }
-#endif /* KSSL_DEBUG */
+ const EVP_AEAD *aead = s->s3->tmp.new_aead;
+ SSL_AEAD_CTX *aead_ctx;
+
+ if (is_read)
+ {
+ if (!tls1_aead_ctx_init(&s->aead_read_ctx))
+ return 0;
+ aead_ctx = s->aead_read_ctx;
+ }
+ else
+ {
+ if (!tls1_aead_ctx_init(&s->aead_write_ctx))
+ return 0;
+ aead_ctx = s->aead_write_ctx;
+ }
+
+ if (!EVP_AEAD_CTX_init(&aead_ctx->ctx, aead, key, key_len,
+ EVP_AEAD_DEFAULT_TAG_LENGTH, NULL /* engine */))
+ return 0;
+ if (iv_len > sizeof(aead_ctx->fixed_nonce))
+ {
+ SSLerr(SSL_F_TLS1_CHANGE_CIPHER_STATE_AEAD, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+ 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))
+ {
+ SSLerr(SSL_F_TLS1_CHANGE_CIPHER_STATE_AEAD, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+ aead_ctx->tag_len = EVP_AEAD_max_overhead(aead);
+
+ return 1;
+ }
+
+/* tls1_change_cipher_state_cipher performs the work needed to switch cipher
+ * states when using EVP_CIPHER. The argument |is_read| is true iff this
+ * function is being called due to reading, as opposed to writing, a
+ * ChangeCipherSpec message. In order to support export ciphersuites,
+ * use_client_keys indicates whether the key material provided is in the
+ * "client write" direction. */
+static int tls1_change_cipher_state_cipher(
+ SSL *s, char is_read, char use_client_keys,
+ const unsigned char *mac_secret, unsigned mac_secret_len,
+ const unsigned char *key, unsigned key_len,
+ const unsigned char *iv, unsigned iv_len)
+ {
+ const EVP_CIPHER *cipher = s->s3->tmp.new_sym_enc;
+ const char is_export = SSL_C_IS_EXPORT(s->s3->tmp.new_cipher) != 0;
+ EVP_CIPHER_CTX *cipher_ctx;
+ EVP_MD_CTX *mac_ctx;
+ char is_aead_cipher;
- if (which & SSL3_CC_READ)
+ unsigned char export_tmp1[EVP_MAX_KEY_LENGTH];
+ unsigned char export_tmp2[EVP_MAX_KEY_LENGTH];
+ unsigned char export_iv1[EVP_MAX_IV_LENGTH * 2];
+ unsigned char export_iv2[EVP_MAX_IV_LENGTH * 2];
+
+ if (is_read)
{
if (s->s3->tmp.new_cipher->algorithm2 & TLS1_STREAM_MAC)
s->mac_flags |= SSL_MAC_FLAG_READ_MAC_STREAM;
@@ -373,19 +409,168 @@ int tls1_change_cipher_state(SSL *s, int which)
s->mac_flags &= ~SSL_MAC_FLAG_READ_MAC_STREAM;
if (s->enc_read_ctx != NULL)
- reuse_dd = 1;
+ EVP_CIPHER_CTX_cleanup(s->enc_read_ctx);
else if ((s->enc_read_ctx=OPENSSL_malloc(sizeof(EVP_CIPHER_CTX))) == NULL)
goto err;
else
/* make sure it's intialized in case we exit later with an error */
EVP_CIPHER_CTX_init(s->enc_read_ctx);
- dd= s->enc_read_ctx;
- mac_ctx=ssl_replace_hash(&s->read_hash,NULL);
+
+ cipher_ctx = s->enc_read_ctx;
+ mac_ctx = ssl_replace_hash(&s->read_hash, NULL);
+
+ memcpy(s->s3->read_mac_secret, mac_secret, mac_secret_len);
+ s->s3->read_mac_secret_size = mac_secret_len;
+ }
+ else
+ {
+ if (s->s3->tmp.new_cipher->algorithm2 & TLS1_STREAM_MAC)
+ s->mac_flags |= SSL_MAC_FLAG_WRITE_MAC_STREAM;
+ else
+ s->mac_flags &= ~SSL_MAC_FLAG_WRITE_MAC_STREAM;
+
+ if (s->enc_write_ctx != NULL)
+ EVP_CIPHER_CTX_cleanup(s->enc_write_ctx);
+ else if ((s->enc_write_ctx=OPENSSL_malloc(sizeof(EVP_CIPHER_CTX))) == NULL)
+ goto err;
+ else
+ /* make sure it's intialized in case we exit later with an error */
+ EVP_CIPHER_CTX_init(s->enc_write_ctx);
+
+ cipher_ctx = s->enc_write_ctx;
+ mac_ctx = ssl_replace_hash(&s->write_hash, NULL);
+
+ memcpy(s->s3->write_mac_secret, mac_secret, mac_secret_len);
+ s->s3->write_mac_secret_size = mac_secret_len;
+ }
+
+ if (is_export)
+ {
+ /* In here I set both the read and write key/iv to the
+ * same value since only the correct one will be used :-).
+ */
+ const unsigned char *label;
+ unsigned label_len;
+
+ if (use_client_keys)
+ {
+ label = (const unsigned char*) TLS_MD_CLIENT_WRITE_KEY_CONST;
+ label_len = TLS_MD_CLIENT_WRITE_KEY_CONST_SIZE;
+ }
+ else
+ {
+ label = (const unsigned char*) TLS_MD_SERVER_WRITE_KEY_CONST;
+ label_len = TLS_MD_SERVER_WRITE_KEY_CONST_SIZE;
+ }
+
+ if (!tls1_PRF(ssl_get_algorithm2(s),
+ label, label_len,
+ s->s3->client_random, SSL3_RANDOM_SIZE,
+ s->s3->server_random, SSL3_RANDOM_SIZE,
+ NULL, 0, NULL, 0,
+ key /* secret */, key_len /* secret length */,
+ export_tmp1 /* output */,
+ export_tmp2 /* scratch space */,
+ EVP_CIPHER_key_length(s->s3->tmp.new_sym_enc) /* output length */))
+ return 0;
+ key = export_tmp1;
+
+ if (iv_len > 0)
+ {
+ static const unsigned char empty[] = "";
+
+ if (!tls1_PRF(ssl_get_algorithm2(s),
+ TLS_MD_IV_BLOCK_CONST, TLS_MD_IV_BLOCK_CONST_SIZE,
+ s->s3->client_random, SSL3_RANDOM_SIZE,
+ s->s3->server_random, SSL3_RANDOM_SIZE,
+ NULL, 0, NULL, 0,
+ empty /* secret */ ,0 /* secret length */,
+ export_iv1 /* output */,
+ export_iv2 /* scratch space */,
+ iv_len * 2 /* output length */))
+ return 0;
+
+ if (use_client_keys)
+ iv = export_iv1;
+ else
+ iv = &export_iv1[iv_len];
+ }
+ }
+
+ /* is_aead_cipher indicates whether the EVP_CIPHER implements an AEAD
+ * interface. This is different from the newer EVP_AEAD interface. */
+ is_aead_cipher = (EVP_CIPHER_flags(cipher) & EVP_CIPH_FLAG_AEAD_CIPHER) != 0;
+
+ if (!is_aead_cipher)
+ {
+ EVP_PKEY *mac_key =
+ EVP_PKEY_new_mac_key(s->s3->tmp.new_mac_pkey_type,
+ NULL, mac_secret, mac_secret_len);
+ if (!mac_key)
+ return 0;
+ EVP_DigestSignInit(mac_ctx, NULL, s->s3->tmp.new_hash, NULL, mac_key);
+ EVP_PKEY_free(mac_key);
+ }
+
+ if (EVP_CIPHER_mode(cipher) == EVP_CIPH_GCM_MODE)
+ {
+ EVP_CipherInit_ex(cipher_ctx, cipher, NULL /* engine */, key,
+ NULL /* iv */, !is_read);
+ EVP_CIPHER_CTX_ctrl(cipher_ctx, EVP_CTRL_GCM_SET_IV_FIXED, iv_len, (void*) iv);
+ }
+ else
+ EVP_CipherInit_ex(cipher_ctx, cipher, NULL /* engine */, key, iv, !is_read);
+
+ /* Needed for "composite" AEADs, such as RC4-HMAC-MD5 */
+ if (is_aead_cipher && mac_secret_len > 0)
+ EVP_CIPHER_CTX_ctrl(cipher_ctx, EVP_CTRL_AEAD_SET_MAC_KEY,
+ mac_secret_len, (void*) mac_secret);
+
+ if (is_export)
+ {
+ OPENSSL_cleanse(export_tmp1, sizeof(export_tmp1));
+ OPENSSL_cleanse(export_tmp2, sizeof(export_tmp1));
+ OPENSSL_cleanse(export_iv1, sizeof(export_iv1));
+ OPENSSL_cleanse(export_iv2, sizeof(export_iv2));
+ }
+
+ return 1;
+
+err:
+ SSLerr(SSL_F_TLS1_CHANGE_CIPHER_STATE_CIPHER, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+
+int tls1_change_cipher_state(SSL *s, int which)
+ {
+ /* is_read is true if we have just read a ChangeCipherSpec message -
+ * i.e. we need to update the read cipherspec. Otherwise we have just
+ * written one. */
+ const char is_read = (which & SSL3_CC_READ) != 0;
+ /* use_client_keys is true if we wish to use the keys for the "client
+ * write" direction. This is the case if we're a client sending a
+ * ChangeCipherSpec, or a server reading a client's ChangeCipherSpec. */
+ const char use_client_keys = which == SSL3_CHANGE_CIPHER_CLIENT_WRITE ||
+ which == SSL3_CHANGE_CIPHER_SERVER_READ;
+ const unsigned char *client_write_mac_secret, *server_write_mac_secret, *mac_secret;
+ const unsigned char *client_write_key, *server_write_key, *key;
+ const unsigned char *client_write_iv, *server_write_iv, *iv;
+ const EVP_CIPHER *cipher = s->s3->tmp.new_sym_enc;
+ const EVP_AEAD *aead = s->s3->tmp.new_aead;
+ unsigned key_len, iv_len, mac_secret_len;
+ const unsigned char *key_data;
+ const char is_export = SSL_C_IS_EXPORT(s->s3->tmp.new_cipher) != 0;
+
+ /* Update compression contexts. */
#ifndef OPENSSL_NO_COMP
+ const SSL_COMP *comp = s->s3->tmp.new_compression;
+
+ if (is_read)
+ {
if (s->expand != NULL)
{
COMP_CTX_free(s->expand);
- s->expand=NULL;
+ s->expand = NULL;
}
if (comp != NULL)
{
@@ -393,197 +578,118 @@ int tls1_change_cipher_state(SSL *s, int which)
if (s->expand == NULL)
{
SSLerr(SSL_F_TLS1_CHANGE_CIPHER_STATE,SSL_R_COMPRESSION_LIBRARY_ERROR);
- goto err2;
+ return 0;
}
if (s->s3->rrec.comp == NULL)
- s->s3->rrec.comp=(unsigned char *)
- OPENSSL_malloc(SSL3_RT_MAX_ENCRYPTED_LENGTH);
+ s->s3->rrec.comp =
+ (unsigned char *)OPENSSL_malloc(SSL3_RT_MAX_ENCRYPTED_LENGTH);
if (s->s3->rrec.comp == NULL)
goto err;
}
-#endif
- /* this is done by dtls1_reset_seq_numbers for DTLS1_VERSION */
- if (s->version != DTLS1_VERSION)
- memset(&(s->s3->read_sequence[0]),0,8);
- mac_secret= &(s->s3->read_mac_secret[0]);
- mac_secret_size=&(s->s3->read_mac_secret_size);
}
else
{
- if (s->s3->tmp.new_cipher->algorithm2 & TLS1_STREAM_MAC)
- s->mac_flags |= SSL_MAC_FLAG_WRITE_MAC_STREAM;
- else
- s->mac_flags &= ~SSL_MAC_FLAG_WRITE_MAC_STREAM;
- if (s->enc_write_ctx != NULL)
- reuse_dd = 1;
- else if ((s->enc_write_ctx=OPENSSL_malloc(sizeof(EVP_CIPHER_CTX))) == NULL)
- goto err;
- else
- /* make sure it's intialized in case we exit later with an error */
- EVP_CIPHER_CTX_init(s->enc_write_ctx);
- dd= s->enc_write_ctx;
- mac_ctx = ssl_replace_hash(&s->write_hash,NULL);
-#ifndef OPENSSL_NO_COMP
if (s->compress != NULL)
{
COMP_CTX_free(s->compress);
- s->compress=NULL;
+ s->compress = NULL;
}
if (comp != NULL)
{
- s->compress=COMP_CTX_new(comp->method);
+ s->compress = COMP_CTX_new(comp->method);
if (s->compress == NULL)
{
SSLerr(SSL_F_TLS1_CHANGE_CIPHER_STATE,SSL_R_COMPRESSION_LIBRARY_ERROR);
- goto err2;
+ return 0;
}
}
-#endif
- /* this is done by dtls1_reset_seq_numbers for DTLS1_VERSION */
- if (s->version != DTLS1_VERSION)
- memset(&(s->s3->write_sequence[0]),0,8);
- mac_secret= &(s->s3->write_mac_secret[0]);
- mac_secret_size = &(s->s3->write_mac_secret_size);
}
+#endif /* OPENSSL_NO_COMP */
- if (reuse_dd)
- EVP_CIPHER_CTX_cleanup(dd);
+ /* Reset sequence number to zero. */
+ memset(is_read ? s->s3->read_sequence : s->s3->write_sequence, 0, 8);
- p=s->s3->tmp.key_block;
- i=*mac_secret_size=s->s3->tmp.new_mac_secret_size;
+ /* key_arg is used for SSLv2. We don't need it for TLS. */
+ s->session->key_arg_length = 0;
- cl=EVP_CIPHER_key_length(c);
- j=is_export ? (cl < SSL_C_EXPORT_KEYLENGTH(s->s3->tmp.new_cipher) ?
- cl : SSL_C_EXPORT_KEYLENGTH(s->s3->tmp.new_cipher)) : cl;
- /* Was j=(exp)?5:EVP_CIPHER_key_length(c); */
- /* If GCM mode only part of IV comes from PRF */
- if (EVP_CIPHER_mode(c) == EVP_CIPH_GCM_MODE)
- k = EVP_GCM_TLS_FIXED_IV_LEN;
- else
- k=EVP_CIPHER_iv_length(c);
- if ( (which == SSL3_CHANGE_CIPHER_CLIENT_WRITE) ||
- (which == SSL3_CHANGE_CIPHER_SERVER_READ))
+ mac_secret_len = s->s3->tmp.new_mac_secret_size;
+
+ if (aead != NULL)
{
- ms= &(p[ 0]); n=i+i;
- key= &(p[ n]); n+=j+j;
- iv= &(p[ n]); n+=k+k;
- exp_label=(unsigned char *)TLS_MD_CLIENT_WRITE_KEY_CONST;
- exp_label_len=TLS_MD_CLIENT_WRITE_KEY_CONST_SIZE;
- client_write=1;
+ key_len = EVP_AEAD_key_length(aead);
+ iv_len = SSL_CIPHER_AEAD_FIXED_NONCE_LEN(s->s3->tmp.new_cipher);
}
else
{
- n=i;
- ms= &(p[ n]); n+=i+j;
- key= &(p[ n]); n+=j+k;
- iv= &(p[ n]); n+=k;
- exp_label=(unsigned char *)TLS_MD_SERVER_WRITE_KEY_CONST;
- exp_label_len=TLS_MD_SERVER_WRITE_KEY_CONST_SIZE;
- client_write=0;
- }
+ key_len = EVP_CIPHER_key_length(cipher);
+ if (is_export && key_len > SSL_C_EXPORT_KEYLENGTH(s->s3->tmp.new_cipher))
+ key_len = SSL_C_EXPORT_KEYLENGTH(s->s3->tmp.new_cipher);
- if (n > s->s3->tmp.key_block_length)
- {
- SSLerr(SSL_F_TLS1_CHANGE_CIPHER_STATE,ERR_R_INTERNAL_ERROR);
- goto err2;
+ if (EVP_CIPHER_mode(cipher) == EVP_CIPH_GCM_MODE)
+ iv_len = EVP_GCM_TLS_FIXED_IV_LEN;
+ else
+ iv_len = EVP_CIPHER_iv_length(cipher);
}
- memcpy(mac_secret,ms,i);
+ key_data = s->s3->tmp.key_block;
+ client_write_mac_secret = key_data; key_data += mac_secret_len;
+ server_write_mac_secret = key_data; key_data += mac_secret_len;
+ client_write_key = key_data; key_data += key_len;
+ server_write_key = key_data; key_data += key_len;
+ client_write_iv = key_data; key_data += iv_len;
+ server_write_iv = key_data; key_data += iv_len;
- if (!(EVP_CIPHER_flags(c)&EVP_CIPH_FLAG_AEAD_CIPHER))
+ if (use_client_keys)
{
- mac_key = EVP_PKEY_new_mac_key(mac_type, NULL,
- mac_secret,*mac_secret_size);
- EVP_DigestSignInit(mac_ctx,NULL,m,NULL,mac_key);
- EVP_PKEY_free(mac_key);
+ mac_secret = client_write_mac_secret;
+ key = client_write_key;
+ iv = client_write_iv;
}
-#ifdef TLS_DEBUG
-printf("which = %04X\nmac key=",which);
-{ int z; for (z=0; z<i; z++) printf("%02X%c",ms[z],((z+1)%16)?' ':'\n'); }
-#endif
- if (is_export)
+ else
{
- /* In here I set both the read and write key/iv to the
- * same value since only the correct one will be used :-).
- */
- if (!tls1_PRF(ssl_get_algorithm2(s),
- exp_label,exp_label_len,
- s->s3->client_random,SSL3_RANDOM_SIZE,
- s->s3->server_random,SSL3_RANDOM_SIZE,
- NULL,0,NULL,0,
- key,j,tmp1,tmp2,EVP_CIPHER_key_length(c)))
- goto err2;
- key=tmp1;
-
- if (k > 0)
- {
- if (!tls1_PRF(ssl_get_algorithm2(s),
- TLS_MD_IV_BLOCK_CONST,TLS_MD_IV_BLOCK_CONST_SIZE,
- s->s3->client_random,SSL3_RANDOM_SIZE,
- s->s3->server_random,SSL3_RANDOM_SIZE,
- NULL,0,NULL,0,
- empty,0,iv1,iv2,k*2))
- goto err2;
- if (client_write)
- iv=iv1;
- else
- iv= &(iv1[k]);
- }
+ mac_secret = server_write_mac_secret;
+ key = server_write_key;
+ iv = server_write_iv;
}
- s->session->key_arg_length=0;
-#ifdef KSSL_DEBUG
- {
- int i;
- printf("EVP_CipherInit_ex(dd,c,key=,iv=,which)\n");
- printf("\tkey= "); for (i=0; i<c->key_len; i++) printf("%02x", key[i]);
- printf("\n");
- printf("\t iv= "); for (i=0; i<c->iv_len; i++) printf("%02x", iv[i]);
- printf("\n");
- }
-#endif /* KSSL_DEBUG */
-
- if (EVP_CIPHER_mode(c) == EVP_CIPH_GCM_MODE)
+ if (key_data - s->s3->tmp.key_block != s->s3->tmp.key_block_length)
{
- EVP_CipherInit_ex(dd,c,NULL,key,NULL,(which & SSL3_CC_WRITE));
- EVP_CIPHER_CTX_ctrl(dd, EVP_CTRL_GCM_SET_IV_FIXED, k, iv);
+ SSLerr(SSL_F_TLS1_CHANGE_CIPHER_STATE,ERR_R_INTERNAL_ERROR);
+ return 0;
}
- else
- EVP_CipherInit_ex(dd,c,NULL,key,iv,(which & SSL3_CC_WRITE));
-
- /* Needed for "composite" AEADs, such as RC4-HMAC-MD5 */
- if ((EVP_CIPHER_flags(c)&EVP_CIPH_FLAG_AEAD_CIPHER) && *mac_secret_size)
- EVP_CIPHER_CTX_ctrl(dd,EVP_CTRL_AEAD_SET_MAC_KEY,
- *mac_secret_size,mac_secret);
-#ifdef TLS_DEBUG
-printf("which = %04X\nkey=",which);
-{ int z; for (z=0; z<EVP_CIPHER_key_length(c); z++) printf("%02X%c",key[z],((z+1)%16)?' ':'\n'); }
-printf("\niv=");
-{ int z; for (z=0; z<k; z++) printf("%02X%c",iv[z],((z+1)%16)?' ':'\n'); }
-printf("\n");
-#endif
+ if (aead != NULL)
+ {
+ if (!tls1_change_cipher_state_aead(s, is_read,
+ key, key_len, iv, iv_len))
+ return 0;
+ }
+ else
+ {
+ if (!tls1_change_cipher_state_cipher(s, is_read, use_client_keys,
+ mac_secret, mac_secret_len,
+ key, key_len,
+ iv, iv_len))
+ return 0;
+ }
- OPENSSL_cleanse(tmp1,sizeof(tmp1));
- OPENSSL_cleanse(tmp2,sizeof(tmp1));
- OPENSSL_cleanse(iv1,sizeof(iv1));
- OPENSSL_cleanse(iv2,sizeof(iv2));
- return(1);
+ return 1;
err:
- SSLerr(SSL_F_TLS1_CHANGE_CIPHER_STATE,ERR_R_MALLOC_FAILURE);
-err2:
- return(0);
+ SSLerr(SSL_F_TLS1_CHANGE_CIPHER_STATE, ERR_R_MALLOC_FAILURE);
+ return 0;
}
int tls1_setup_key_block(SSL *s)
{
unsigned char *p1,*p2=NULL;
- const EVP_CIPHER *c;
- const EVP_MD *hash;
+ const EVP_CIPHER *c = NULL;
+ const EVP_MD *hash = NULL;
+ const EVP_AEAD *aead = NULL;
int num;
SSL_COMP *comp;
int mac_type= NID_undef,mac_secret_size=0;
int ret=0;
+ unsigned key_len, iv_len;
#ifdef KSSL_DEBUG
printf ("tls1_setup_key_block()\n");
@@ -592,17 +698,36 @@ int tls1_setup_key_block(SSL *s)
if (s->s3->tmp.key_block_length != 0)
return(1);
- if (!ssl_cipher_get_evp(s->session,&c,&hash,&mac_type,&mac_secret_size,&comp))
+ if (!ssl_cipher_get_comp(s->session, &comp))
+ goto cipher_unavailable_err;
+
+ if (s->session->cipher &&
+ (s->session->cipher->algorithm2 & SSL_CIPHER_ALGORITHM2_AEAD))
{
- SSLerr(SSL_F_TLS1_SETUP_KEY_BLOCK,SSL_R_CIPHER_OR_HASH_UNAVAILABLE);
- return(0);
+ if (!ssl_cipher_get_evp_aead(s->session, &aead))
+ goto cipher_unavailable_err;
+ key_len = EVP_AEAD_key_length(aead);
+ iv_len = SSL_CIPHER_AEAD_FIXED_NONCE_LEN(s->session->cipher);
+ }
+ else
+ {
+ if (!ssl_cipher_get_evp(s->session,&c,&hash,&mac_type,&mac_secret_size))
+ goto cipher_unavailable_err;
+ key_len = EVP_CIPHER_key_length(c);
+
+ if (EVP_CIPHER_mode(c) == EVP_CIPH_GCM_MODE)
+ iv_len = EVP_GCM_TLS_FIXED_IV_LEN;
+ else
+ iv_len = EVP_CIPHER_iv_length(c);
}
+ s->s3->tmp.new_aead=aead;
s->s3->tmp.new_sym_enc=c;
s->s3->tmp.new_hash=hash;
s->s3->tmp.new_mac_pkey_type = mac_type;
s->s3->tmp.new_mac_secret_size = mac_secret_size;
- num=EVP_CIPHER_key_length(c)+mac_secret_size+EVP_CIPHER_iv_length(c);
+
+ num=key_len+mac_secret_size+iv_len;
num*=2;
ssl3_cleanup_key_block(s);
@@ -665,6 +790,10 @@ err:
OPENSSL_free(p2);
}
return(ret);
+
+cipher_unavailable_err:
+ SSLerr(SSL_F_TLS1_SETUP_KEY_BLOCK,SSL_R_CIPHER_OR_HASH_UNAVAILABLE);
+ return 0;
}
/* tls1_enc encrypts/decrypts the record in |s->wrec| / |s->rrec|, respectively.
@@ -683,6 +812,134 @@ int tls1_enc(SSL *s, int send)
unsigned long l;
int bs,i,j,k,pad=0,ret,mac_size=0;
const EVP_CIPHER *enc;
+ const SSL_AEAD_CTX *aead;
+
+ if (send)
+ rec = &s->s3->wrec;
+ else
+ rec = &s->s3->rrec;
+
+ if (send)
+ aead = s->aead_write_ctx;
+ else
+ aead = s->aead_read_ctx;
+
+ if (aead)
+ {
+ unsigned char ad[13], *seq, *in, *out, nonce[16];
+ unsigned nonce_used;
+ ssize_t n;
+
+ seq = send ? s->s3->write_sequence : s->s3->read_sequence;
+
+ if (s->version == DTLS1_VERSION || s->version == DTLS1_BAD_VER)
+ {
+ unsigned char dtlsseq[9], *p = dtlsseq;
+
+ s2n(send ? s->d1->w_epoch : s->d1->r_epoch, p);
+ memcpy(p, &seq[2], 6);
+ memcpy(ad, dtlsseq, 8);
+ }
+ else
+ {
+ memcpy(ad, seq, 8);
+ for (i=7; i>=0; i--) /* increment */
+ {
+ ++seq[i];
+ if (seq[i] != 0)
+ break;
+ }
+ }
+
+ ad[8] = rec->type;
+ ad[9] = (unsigned char)(s->version>>8);
+ ad[10] = (unsigned char)(s->version);
+
+ if (aead->fixed_nonce_len + aead->variable_nonce_len > sizeof(nonce) ||
+ aead->variable_nonce_len > 8)
+ return -1; /* internal error - should never happen. */
+
+ memcpy(nonce, aead->fixed_nonce, aead->fixed_nonce_len);
+ nonce_used = aead->fixed_nonce_len;
+
+ if (send)
+ {
+ size_t len = rec->length;
+ size_t eivlen = 0;
+ in = rec->input;
+ out = rec->data;
+
+ /* When sending we use the sequence number as the
+ * variable part of the nonce. */
+ if (aead->variable_nonce_len > 8)
+ return -1;
+ memcpy(nonce + nonce_used, ad, aead->variable_nonce_len);
+ nonce_used += aead->variable_nonce_len;
+
+ /* in do_ssl3_write, rec->input is moved forward by
+ * variable_nonce_len in order to leave space for the
+ * variable nonce. Thus we can copy the sequence number
+ * bytes into place without overwriting any of the
+ * plaintext. */
+ 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;
+
+ n = EVP_AEAD_CTX_seal(&aead->ctx,
+ out + eivlen, len + aead->tag_len,
+ nonce, nonce_used,
+ in + eivlen, len,
+ ad, sizeof(ad));
+ if (n >= 0 && aead->variable_nonce_included_in_record)
+ n += aead->variable_nonce_len;
+ }
+ else
+ {
+ /* receive */
+ size_t len = rec->length;
+
+ if (rec->data != rec->input)
+ return -1; /* internal error - should never happen. */
+ out = in = rec->input;
+
+ if (len < aead->variable_nonce_len)
+ return 0;
+ memcpy(nonce + nonce_used,
+ aead->variable_nonce_included_in_record ? in : ad,
+ aead->variable_nonce_len);
+ nonce_used += 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;
+ len -= aead->tag_len;
+
+ ad[11] = len >> 8;
+ ad[12] = len & 0xff;
+
+ n = EVP_AEAD_CTX_open(&aead->ctx, out, len, nonce, nonce_used,
+ in, len + aead->tag_len, ad, sizeof(ad));
+
+ rec->data = rec->input = out;
+ }
+
+ if (n == -1)
+ return -1;
+ rec->length = n;
+ return 1;
+ }
if (send)
{
diff --git a/openssl/ssl/tls1.h b/openssl/ssl/tls1.h
index 8fc1ff4..0ce0193 100644
--- a/openssl/ssl/tls1.h
+++ b/openssl/ssl/tls1.h
@@ -522,6 +522,10 @@ SSL_CTX_callback_ctrl(ssl,SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB,(void (*)(void))cb)
#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
@@ -673,6 +677,10 @@ SSL_CTX_callback_ctrl(ssl,SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB,(void (*)(void))cb)
#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