blob: 7f607d0c2896b1a6e93b30982ac26989fd87b44e [file] [log] [blame]
diff -burN android-openssl.orig/include/openssl/ssl.h android-openssl/include/openssl/ssl.h
--- android-openssl.orig/include/openssl/ssl.h 2014-05-05 16:45:02.685389339 +0200
+++ android-openssl/include/openssl/ssl.h 2014-05-05 16:46:32.513390565 +0200
@@ -544,6 +544,13 @@
#ifndef OPENSSL_NO_SRP
char *srp_username;
#endif
+
+ /* original_handshake_hash contains the handshake hash (either
+ * SHA-1+MD5 or SHA-2, depending on TLS version) for the original, full
+ * handshake that created a session. This is used by Channel IDs during
+ * resumption. */
+ unsigned char original_handshake_hash[EVP_MAX_MD_SIZE];
+ unsigned int original_handshake_hash_len;
};
#endif
diff -burN android-openssl.orig/include/openssl/tls1.h android-openssl/include/openssl/tls1.h
--- android-openssl.orig/include/openssl/tls1.h 2014-05-05 16:45:02.689389339 +0200
+++ android-openssl/include/openssl/tls1.h 2014-05-05 16:46:32.517390565 +0200
@@ -249,7 +249,7 @@
#endif
/* This is not an IANA defined extension number */
-#define TLSEXT_TYPE_channel_id 30031
+#define TLSEXT_TYPE_channel_id 30032
/* NameType value from RFC 3546 */
#define TLSEXT_NAMETYPE_host_name 0
diff -burN android-openssl.orig/patches/new_channelid.patch android-openssl/patches/new_channelid.patch
--- android-openssl.orig/patches/new_channelid.patch 1970-01-01 01:00:00.000000000 +0100
+++ android-openssl/patches/new_channelid.patch 2014-05-05 16:48:54.429392502 +0200
@@ -0,0 +1,273 @@
+diff --git a/include/openssl/ssl.h b/include/openssl/ssl.h
+index a3944f1..fe92ccf 100644
+--- a/include/openssl/ssl.h
++++ b/include/openssl/ssl.h
+@@ -547,6 +547,13 @@ struct ssl_session_st
+ #ifndef OPENSSL_NO_SRP
+ char *srp_username;
+ #endif
++
++ /* original_handshake_hash contains the handshake hash (either
++ * SHA-1+MD5 or SHA-2, depending on TLS version) for the original, full
++ * handshake that created a session. This is used by Channel IDs during
++ * resumption. */
++ unsigned char original_handshake_hash[EVP_MAX_MD_SIZE];
++ unsigned int original_handshake_hash_len;
+ };
+
+ #endif
+diff --git a/include/openssl/tls1.h b/include/openssl/tls1.h
+index c4f69aa..5559486 100644
+--- a/include/openssl/tls1.h
++++ b/include/openssl/tls1.h
+@@ -255,7 +255,7 @@ extern "C" {
+ #endif
+
+ /* This is not an IANA defined extension number */
+-#define TLSEXT_TYPE_channel_id 30031
++#define TLSEXT_TYPE_channel_id 30032
+
+ /* NameType value from RFC 3546 */
+ #define TLSEXT_NAMETYPE_host_name 0
+diff --git a/ssl/s3_clnt.c b/ssl/s3_clnt.c
+index 640df80..d6154c5 100644
+--- a/ssl/s3_clnt.c
++++ b/ssl/s3_clnt.c
+@@ -583,6 +583,18 @@ int ssl3_connect(SSL *s)
+ #endif
+ s->s3->tmp.next_state=SSL3_ST_CR_FINISHED_A;
+ }
++ if (s->s3->tlsext_channel_id_valid)
++ {
++ /* This is a non-resumption handshake. If it
++ * involves ChannelID, then record the
++ * handshake hashes at this point in the
++ * session so that any resumption of this
++ * session with ChannelID can sign those
++ * hashes. */
++ ret = tls1_record_handshake_hashes_for_channel_id(s);
++ if (ret <= 0)
++ goto end;
++ }
+ }
+ s->init_num=0;
+ break;
+diff --git a/ssl/ssl.h b/ssl/ssl.h
+index a3944f1..fe92ccf 100644
+--- a/ssl/ssl.h
++++ b/ssl/ssl.h
+@@ -547,6 +547,13 @@ struct ssl_session_st
+ #ifndef OPENSSL_NO_SRP
+ char *srp_username;
+ #endif
++
++ /* original_handshake_hash contains the handshake hash (either
++ * SHA-1+MD5 or SHA-2, depending on TLS version) for the original, full
++ * handshake that created a session. This is used by Channel IDs during
++ * resumption. */
++ unsigned char original_handshake_hash[EVP_MAX_MD_SIZE];
++ unsigned int original_handshake_hash_len;
+ };
+
+ #endif
+diff --git a/ssl/ssl_locl.h b/ssl/ssl_locl.h
+index 531a291..c975d31 100644
+--- a/ssl/ssl_locl.h
++++ b/ssl/ssl_locl.h
+@@ -1102,6 +1102,7 @@ void ssl_free_wbio_buffer(SSL *s);
+ int tls1_change_cipher_state(SSL *s, int which);
+ int tls1_setup_key_block(SSL *s);
+ int tls1_enc(SSL *s, int snd);
++int tls1_handshake_digest(SSL *s, unsigned char *out, size_t out_len);
+ int tls1_final_finish_mac(SSL *s,
+ const char *str, int slen, unsigned char *p);
+ int tls1_cert_verify_mac(SSL *s, int md_nid, unsigned char *p);
+@@ -1158,6 +1159,7 @@ int tls12_get_sigid(const EVP_PKEY *pk);
+ const EVP_MD *tls12_get_hash(unsigned char hash_alg);
+
+ int tls1_channel_id_hash(EVP_MD_CTX *ctx, SSL *s);
++int tls1_record_handshake_hashes_for_channel_id(SSL *s);
+ #endif
+
+ int ssl3_can_cutthrough(const SSL *s);
+diff --git a/ssl/t1_enc.c b/ssl/t1_enc.c
+index 87b7021..d30ce61 100644
+--- a/ssl/t1_enc.c
++++ b/ssl/t1_enc.c
+@@ -1147,53 +1147,79 @@ int tls1_cert_verify_mac(SSL *s, int md_nid, unsigned char *out)
+ return((int)ret);
+ }
+
++/* tls1_handshake_digest calculates the current handshake hash and writes it to
++ * |out|, which has space for |out_len| bytes. It returns the number of bytes
++ * written or -1 in the event of an error. This function works on a copy of the
++ * underlying digests so can be called multiple times and prior to the final
++ * update etc. */
++int tls1_handshake_digest(SSL *s, unsigned char *out, size_t out_len)
++ {
++ const EVP_MD *md;
++ EVP_MD_CTX ctx;
++ int i, err = 0, len = 0;
++ long mask;
++
++ EVP_MD_CTX_init(&ctx);
++
++ for (i = 0; ssl_get_handshake_digest(i, &mask, &md); i++)
++ {
++ int hash_size;
++ unsigned int digest_len;
++ EVP_MD_CTX *hdgst = s->s3->handshake_dgst[i];
++
++ if ((mask & ssl_get_algorithm2(s)) == 0)
++ continue;
++
++ hash_size = EVP_MD_size(md);
++ if (!hdgst || hash_size < 0 || (size_t)hash_size > out_len)
++ {
++ err = 1;
++ break;
++ }
++
++ if (!EVP_MD_CTX_copy_ex(&ctx, hdgst) ||
++ !EVP_DigestFinal_ex(&ctx, out, &digest_len) ||
++ digest_len != (unsigned int)hash_size) /* internal error */
++ {
++ err = 1;
++ break;
++ }
++ out += digest_len;
++ out_len -= digest_len;
++ len += digest_len;
++ }
++
++ EVP_MD_CTX_cleanup(&ctx);
++
++ if (err != 0)
++ return -1;
++ return len;
++ }
++
+ int tls1_final_finish_mac(SSL *s,
+ const char *str, int slen, unsigned char *out)
+ {
+- unsigned int i;
+- EVP_MD_CTX ctx;
+ unsigned char buf[2*EVP_MAX_MD_SIZE];
+- unsigned char *q,buf2[12];
+- int idx;
+- long mask;
++ unsigned char buf2[12];
+ int err=0;
+- const EVP_MD *md;
++ int digests_len;
+
+- q=buf;
+-
+- if (s->s3->handshake_buffer)
++ if (s->s3->handshake_buffer)
+ if (!ssl3_digest_cached_records(s))
+ return 0;
+
+- EVP_MD_CTX_init(&ctx);
+-
+- for (idx=0;ssl_get_handshake_digest(idx,&mask,&md);idx++)
++ digests_len = tls1_handshake_digest(s, buf, sizeof(buf));
++ if (digests_len < 0)
+ {
+- if (mask & ssl_get_algorithm2(s))
+- {
+- int hashsize = EVP_MD_size(md);
+- if (hashsize < 0 || hashsize > (int)(sizeof buf - (size_t)(q-buf)))
+- {
+- /* internal error: 'buf' is too small for this cipersuite! */
+- err = 1;
+- }
+- else
+- {
+- EVP_MD_CTX_copy_ex(&ctx,s->s3->handshake_dgst[idx]);
+- EVP_DigestFinal_ex(&ctx,q,&i);
+- if (i != (unsigned int)hashsize) /* can't really happen */
+- err = 1;
+- q+=i;
+- }
+- }
++ err = 1;
++ digests_len = 0;
+ }
+-
++
+ if (!tls1_PRF(ssl_get_algorithm2(s),
+- str,slen, buf,(int)(q-buf), NULL,0, NULL,0, NULL,0,
++ str,slen, buf, digests_len, NULL,0, NULL,0, NULL,0,
+ s->session->master_key,s->session->master_key_length,
+ out,buf2,sizeof buf2))
+ err = 1;
+- EVP_MD_CTX_cleanup(&ctx);
+
+ if (err)
+ return 0;
+diff --git a/ssl/t1_lib.c b/ssl/t1_lib.c
+index ea7fefa..d7ea9a5 100644
+--- a/ssl/t1_lib.c
++++ b/ssl/t1_lib.c
+@@ -2684,6 +2684,17 @@ tls1_channel_id_hash(EVP_MD_CTX *md, SSL *s)
+
+ EVP_DigestUpdate(md, kClientIDMagic, sizeof(kClientIDMagic));
+
++ if (s->hit)
++ {
++ static const char kResumptionMagic[] = "Resumption";
++ EVP_DigestUpdate(md, kResumptionMagic,
++ sizeof(kResumptionMagic));
++ if (s->session->original_handshake_hash_len == 0)
++ return 0;
++ EVP_DigestUpdate(md, s->session->original_handshake_hash,
++ s->session->original_handshake_hash_len);
++ }
++
+ EVP_MD_CTX_init(&ctx);
+ for (i = 0; i < SSL_MAX_DIGEST; i++)
+ {
+@@ -2698,3 +2709,29 @@ tls1_channel_id_hash(EVP_MD_CTX *md, SSL *s)
+ return 1;
+ }
+ #endif
++
++/* tls1_record_handshake_hashes_for_channel_id records the current handshake
++ * hashes in |s->session| so that Channel ID resumptions can sign that data. */
++int tls1_record_handshake_hashes_for_channel_id(SSL *s)
++ {
++ int digest_len;
++ /* This function should never be called for a resumed session because
++ * the handshake hashes that we wish to record are for the original,
++ * full handshake. */
++ if (s->hit)
++ return -1;
++ /* It only makes sense to call this function if Channel IDs have been
++ * negotiated. */
++ if (!s->s3->tlsext_channel_id_valid)
++ return -1;
++
++ digest_len = tls1_handshake_digest(
++ s, s->session->original_handshake_hash,
++ sizeof(s->session->original_handshake_hash));
++ if (digest_len < 0)
++ return -1;
++
++ s->session->original_handshake_hash_len = digest_len;
++
++ return 1;
++ }
+diff --git a/ssl/tls1.h b/ssl/tls1.h
+index c4f69aa..5559486 100644
+--- a/ssl/tls1.h
++++ b/ssl/tls1.h
+@@ -255,7 +255,7 @@ extern "C" {
+ #endif
+
+ /* This is not an IANA defined extension number */
+-#define TLSEXT_TYPE_channel_id 30031
++#define TLSEXT_TYPE_channel_id 30032
+
+ /* NameType value from RFC 3546 */
+ #define TLSEXT_NAMETYPE_host_name 0
diff -burN android-openssl.orig/ssl/s3_clnt.c android-openssl/ssl/s3_clnt.c
--- android-openssl.orig/ssl/s3_clnt.c 2014-05-05 16:45:02.785389340 +0200
+++ android-openssl/ssl/s3_clnt.c 2014-05-05 16:46:32.525390565 +0200
@@ -583,6 +583,18 @@
#endif
s->s3->tmp.next_state=SSL3_ST_CR_FINISHED_A;
}
+ if (s->s3->tlsext_channel_id_valid)
+ {
+ /* This is a non-resumption handshake. If it
+ * involves ChannelID, then record the
+ * handshake hashes at this point in the
+ * session so that any resumption of this
+ * session with ChannelID can sign those
+ * hashes. */
+ ret = tls1_record_handshake_hashes_for_channel_id(s);
+ if (ret <= 0)
+ goto end;
+ }
}
s->init_num=0;
break;
diff -burN android-openssl.orig/ssl/ssl.h android-openssl/ssl/ssl.h
--- android-openssl.orig/ssl/ssl.h 2014-05-05 16:45:02.693389339 +0200
+++ android-openssl/ssl/ssl.h 2014-05-05 16:46:32.533390565 +0200
@@ -544,6 +544,13 @@
#ifndef OPENSSL_NO_SRP
char *srp_username;
#endif
+
+ /* original_handshake_hash contains the handshake hash (either
+ * SHA-1+MD5 or SHA-2, depending on TLS version) for the original, full
+ * handshake that created a session. This is used by Channel IDs during
+ * resumption. */
+ unsigned char original_handshake_hash[EVP_MAX_MD_SIZE];
+ unsigned int original_handshake_hash_len;
};
#endif
diff -burN android-openssl.orig/ssl/ssl_locl.h android-openssl/ssl/ssl_locl.h
--- android-openssl.orig/ssl/ssl_locl.h 2014-05-05 16:45:02.785389340 +0200
+++ android-openssl/ssl/ssl_locl.h 2014-05-05 16:46:32.541390565 +0200
@@ -1071,6 +1071,7 @@
int tls1_change_cipher_state(SSL *s, int which);
int tls1_setup_key_block(SSL *s);
int tls1_enc(SSL *s, int snd);
+int tls1_handshake_digest(SSL *s, unsigned char *out, size_t out_len);
int tls1_final_finish_mac(SSL *s,
const char *str, int slen, unsigned char *p);
int tls1_cert_verify_mac(SSL *s, int md_nid, unsigned char *p);
@@ -1127,6 +1128,7 @@
const EVP_MD *tls12_get_hash(unsigned char hash_alg);
int tls1_channel_id_hash(EVP_MD_CTX *ctx, SSL *s);
+int tls1_record_handshake_hashes_for_channel_id(SSL *s);
#endif
int ssl3_can_cutthrough(const SSL *s);
diff -burN android-openssl.orig/ssl/t1_enc.c android-openssl/ssl/t1_enc.c
--- android-openssl.orig/ssl/t1_enc.c 2014-05-05 16:45:02.697389339 +0200
+++ android-openssl/ssl/t1_enc.c 2014-05-05 16:46:32.545390565 +0200
@@ -890,53 +890,79 @@
return((int)ret);
}
-int tls1_final_finish_mac(SSL *s,
- const char *str, int slen, unsigned char *out)
+/* tls1_handshake_digest calculates the current handshake hash and writes it to
+ * |out|, which has space for |out_len| bytes. It returns the number of bytes
+ * written or -1 in the event of an error. This function works on a copy of the
+ * underlying digests so can be called multiple times and prior to the final
+ * update etc. */
+int tls1_handshake_digest(SSL *s, unsigned char *out, size_t out_len)
{
- unsigned int i;
+ const EVP_MD *md;
EVP_MD_CTX ctx;
- unsigned char buf[2*EVP_MAX_MD_SIZE];
- unsigned char *q,buf2[12];
- int idx;
+ int i, err = 0, len = 0;
long mask;
- int err=0;
- const EVP_MD *md;
-
- q=buf;
-
- if (s->s3->handshake_buffer)
- if (!ssl3_digest_cached_records(s))
- return 0;
EVP_MD_CTX_init(&ctx);
- for (idx=0;ssl_get_handshake_digest(idx,&mask,&md);idx++)
+ for (i = 0; ssl_get_handshake_digest(i, &mask, &md); i++)
{
- if (mask & ssl_get_algorithm2(s))
- {
- int hashsize = EVP_MD_size(md);
- if (hashsize < 0 || hashsize > (int)(sizeof buf - (size_t)(q-buf)))
+ int hash_size;
+ unsigned int digest_len;
+ EVP_MD_CTX *hdgst = s->s3->handshake_dgst[i];
+
+ if ((mask & ssl_get_algorithm2(s)) == 0)
+ continue;
+
+ hash_size = EVP_MD_size(md);
+ if (!hdgst || hash_size < 0 || (size_t)hash_size > out_len)
{
- /* internal error: 'buf' is too small for this cipersuite! */
err = 1;
+ break;
}
- else
+
+ if (!EVP_MD_CTX_copy_ex(&ctx, hdgst) ||
+ !EVP_DigestFinal_ex(&ctx, out, &digest_len) ||
+ digest_len != (unsigned int)hash_size) /* internal error */
{
- EVP_MD_CTX_copy_ex(&ctx,s->s3->handshake_dgst[idx]);
- EVP_DigestFinal_ex(&ctx,q,&i);
- if (i != (unsigned int)hashsize) /* can't really happen */
err = 1;
- q+=i;
+ break;
}
+ out += digest_len;
+ out_len -= digest_len;
+ len += digest_len;
}
+
+ EVP_MD_CTX_cleanup(&ctx);
+
+ if (err != 0)
+ return -1;
+ return len;
+ }
+
+int tls1_final_finish_mac(SSL *s,
+ const char *str, int slen, unsigned char *out)
+ {
+ unsigned char buf[2*EVP_MAX_MD_SIZE];
+ unsigned char buf2[12];
+ int err=0;
+ int digests_len;
+
+ if (s->s3->handshake_buffer)
+ if (!ssl3_digest_cached_records(s))
+ return 0;
+
+ digests_len = tls1_handshake_digest(s, buf, sizeof(buf));
+ if (digests_len < 0)
+ {
+ err = 1;
+ digests_len = 0;
}
if (!tls1_PRF(ssl_get_algorithm2(s),
- str,slen, buf,(int)(q-buf), NULL,0, NULL,0, NULL,0,
+ str,slen, buf, digests_len, NULL,0, NULL,0, NULL,0,
s->session->master_key,s->session->master_key_length,
out,buf2,sizeof buf2))
err = 1;
- EVP_MD_CTX_cleanup(&ctx);
if (err)
return 0;
diff -burN android-openssl.orig/ssl/t1_lib.c android-openssl/ssl/t1_lib.c
--- android-openssl.orig/ssl/t1_lib.c 2014-05-05 16:45:02.789389340 +0200
+++ android-openssl/ssl/t1_lib.c 2014-05-05 16:46:32.549390565 +0200
@@ -2672,6 +2672,17 @@
EVP_DigestUpdate(md, kClientIDMagic, sizeof(kClientIDMagic));
+ if (s->hit)
+ {
+ static const char kResumptionMagic[] = "Resumption";
+ EVP_DigestUpdate(md, kResumptionMagic,
+ sizeof(kResumptionMagic));
+ if (s->session->original_handshake_hash_len == 0)
+ return 0;
+ EVP_DigestUpdate(md, s->session->original_handshake_hash,
+ s->session->original_handshake_hash_len);
+ }
+
EVP_MD_CTX_init(&ctx);
for (i = 0; i < SSL_MAX_DIGEST; i++)
{
@@ -2686,3 +2697,29 @@
return 1;
}
#endif
+
+/* tls1_record_handshake_hashes_for_channel_id records the current handshake
+ * hashes in |s->session| so that Channel ID resumptions can sign that data. */
+int tls1_record_handshake_hashes_for_channel_id(SSL *s)
+ {
+ int digest_len;
+ /* This function should never be called for a resumed session because
+ * the handshake hashes that we wish to record are for the original,
+ * full handshake. */
+ if (s->hit)
+ return -1;
+ /* It only makes sense to call this function if Channel IDs have been
+ * negotiated. */
+ if (!s->s3->tlsext_channel_id_valid)
+ return -1;
+
+ digest_len = tls1_handshake_digest(
+ s, s->session->original_handshake_hash,
+ sizeof(s->session->original_handshake_hash));
+ if (digest_len < 0)
+ return -1;
+
+ s->session->original_handshake_hash_len = digest_len;
+
+ return 1;
+ }
diff -burN android-openssl.orig/ssl/tls1.h android-openssl/ssl/tls1.h
--- android-openssl.orig/ssl/tls1.h 2014-05-05 16:45:02.697389339 +0200
+++ android-openssl/ssl/tls1.h 2014-05-05 16:46:32.553390566 +0200
@@ -249,7 +249,7 @@
#endif
/* This is not an IANA defined extension number */
-#define TLSEXT_TYPE_channel_id 30031
+#define TLSEXT_TYPE_channel_id 30032
/* NameType value from RFC 3546 */
#define TLSEXT_NAMETYPE_host_name 0