OLD | NEW |
(Empty) | |
| 1 diff --git a/include/openssl/ssl.h b/include/openssl/ssl.h |
| 2 index a3944f1..fe92ccf 100644 |
| 3 --- a/include/openssl/ssl.h |
| 4 +++ b/include/openssl/ssl.h |
| 5 @@ -547,6 +547,13 @@ struct ssl_session_st |
| 6 #ifndef OPENSSL_NO_SRP |
| 7 char *srp_username; |
| 8 #endif |
| 9 + |
| 10 + /* original_handshake_hash contains the handshake hash (either |
| 11 + * SHA-1+MD5 or SHA-2, depending on TLS version) for the original, full |
| 12 + * handshake that created a session. This is used by Channel IDs during |
| 13 + * resumption. */ |
| 14 + unsigned char original_handshake_hash[EVP_MAX_MD_SIZE]; |
| 15 + unsigned int original_handshake_hash_len; |
| 16 }; |
| 17 |
| 18 #endif |
| 19 diff --git a/include/openssl/tls1.h b/include/openssl/tls1.h |
| 20 index c4f69aa..5559486 100644 |
| 21 --- a/include/openssl/tls1.h |
| 22 +++ b/include/openssl/tls1.h |
| 23 @@ -255,7 +255,7 @@ extern "C" { |
| 24 #endif |
| 25 |
| 26 /* This is not an IANA defined extension number */ |
| 27 -#define TLSEXT_TYPE_channel_id 30031 |
| 28 +#define TLSEXT_TYPE_channel_id 30032 |
| 29 |
| 30 /* NameType value from RFC 3546 */ |
| 31 #define TLSEXT_NAMETYPE_host_name 0 |
| 32 diff --git a/ssl/s3_clnt.c b/ssl/s3_clnt.c |
| 33 index 640df80..d6154c5 100644 |
| 34 --- a/ssl/s3_clnt.c |
| 35 +++ b/ssl/s3_clnt.c |
| 36 @@ -583,6 +583,18 @@ int ssl3_connect(SSL *s) |
| 37 #endif |
| 38 s->s3->tmp.next_state=SSL3_ST_CR
_FINISHED_A; |
| 39 } |
| 40 + if (s->s3->tlsext_channel_id_valid) |
| 41 + { |
| 42 + /* This is a non-resumption handshake. I
f it |
| 43 + * involves ChannelID, then record the |
| 44 + * handshake hashes at this point in the |
| 45 + * session so that any resumption of thi
s |
| 46 + * session with ChannelID can sign those |
| 47 + * hashes. */ |
| 48 + ret = tls1_record_handshake_hashes_for_c
hannel_id(s); |
| 49 + if (ret <= 0) |
| 50 + goto end; |
| 51 + } |
| 52 } |
| 53 s->init_num=0; |
| 54 break; |
| 55 diff --git a/ssl/ssl.h b/ssl/ssl.h |
| 56 index a3944f1..fe92ccf 100644 |
| 57 --- a/ssl/ssl.h |
| 58 +++ b/ssl/ssl.h |
| 59 @@ -547,6 +547,13 @@ struct ssl_session_st |
| 60 #ifndef OPENSSL_NO_SRP |
| 61 char *srp_username; |
| 62 #endif |
| 63 + |
| 64 + /* original_handshake_hash contains the handshake hash (either |
| 65 + * SHA-1+MD5 or SHA-2, depending on TLS version) for the original, full |
| 66 + * handshake that created a session. This is used by Channel IDs during |
| 67 + * resumption. */ |
| 68 + unsigned char original_handshake_hash[EVP_MAX_MD_SIZE]; |
| 69 + unsigned int original_handshake_hash_len; |
| 70 }; |
| 71 |
| 72 #endif |
| 73 diff --git a/ssl/ssl_locl.h b/ssl/ssl_locl.h |
| 74 index 531a291..c975d31 100644 |
| 75 --- a/ssl/ssl_locl.h |
| 76 +++ b/ssl/ssl_locl.h |
| 77 @@ -1102,6 +1102,7 @@ void ssl_free_wbio_buffer(SSL *s); |
| 78 int tls1_change_cipher_state(SSL *s, int which); |
| 79 int tls1_setup_key_block(SSL *s); |
| 80 int tls1_enc(SSL *s, int snd); |
| 81 +int tls1_handshake_digest(SSL *s, unsigned char *out, size_t out_len); |
| 82 int tls1_final_finish_mac(SSL *s, |
| 83 const char *str, int slen, unsigned char *p); |
| 84 int tls1_cert_verify_mac(SSL *s, int md_nid, unsigned char *p); |
| 85 @@ -1158,6 +1159,7 @@ int tls12_get_sigid(const EVP_PKEY *pk); |
| 86 const EVP_MD *tls12_get_hash(unsigned char hash_alg); |
| 87 |
| 88 int tls1_channel_id_hash(EVP_MD_CTX *ctx, SSL *s); |
| 89 +int tls1_record_handshake_hashes_for_channel_id(SSL *s); |
| 90 #endif |
| 91 |
| 92 int ssl3_can_cutthrough(const SSL *s); |
| 93 diff --git a/ssl/t1_enc.c b/ssl/t1_enc.c |
| 94 index 87b7021..d30ce61 100644 |
| 95 --- a/ssl/t1_enc.c |
| 96 +++ b/ssl/t1_enc.c |
| 97 @@ -1147,53 +1147,79 @@ int tls1_cert_verify_mac(SSL *s, int md_nid, unsigned ch
ar *out) |
| 98 return((int)ret); |
| 99 } |
| 100 |
| 101 +/* tls1_handshake_digest calculates the current handshake hash and writes it to |
| 102 + * |out|, which has space for |out_len| bytes. It returns the number of bytes |
| 103 + * written or -1 in the event of an error. This function works on a copy of the |
| 104 + * underlying digests so can be called multiple times and prior to the final |
| 105 + * update etc. */ |
| 106 +int tls1_handshake_digest(SSL *s, unsigned char *out, size_t out_len) |
| 107 + { |
| 108 + const EVP_MD *md; |
| 109 + EVP_MD_CTX ctx; |
| 110 + int i, err = 0, len = 0; |
| 111 + long mask; |
| 112 + |
| 113 + EVP_MD_CTX_init(&ctx); |
| 114 + |
| 115 + for (i = 0; ssl_get_handshake_digest(i, &mask, &md); i++) |
| 116 + { |
| 117 + int hash_size; |
| 118 + unsigned int digest_len; |
| 119 + EVP_MD_CTX *hdgst = s->s3->handshake_dgst[i]; |
| 120 + |
| 121 + if ((mask & ssl_get_algorithm2(s)) == 0) |
| 122 + continue; |
| 123 + |
| 124 + hash_size = EVP_MD_size(md); |
| 125 + if (!hdgst || hash_size < 0 || (size_t)hash_size > out_len) |
| 126 + { |
| 127 + err = 1; |
| 128 + break; |
| 129 + } |
| 130 + |
| 131 + if (!EVP_MD_CTX_copy_ex(&ctx, hdgst) || |
| 132 + !EVP_DigestFinal_ex(&ctx, out, &digest_len) || |
| 133 + digest_len != (unsigned int)hash_size) /* internal error */ |
| 134 + { |
| 135 + err = 1; |
| 136 + break; |
| 137 + } |
| 138 + out += digest_len; |
| 139 + out_len -= digest_len; |
| 140 + len += digest_len; |
| 141 + } |
| 142 + |
| 143 + EVP_MD_CTX_cleanup(&ctx); |
| 144 + |
| 145 + if (err != 0) |
| 146 + return -1; |
| 147 + return len; |
| 148 + } |
| 149 + |
| 150 int tls1_final_finish_mac(SSL *s, |
| 151 const char *str, int slen, unsigned char *out) |
| 152 { |
| 153 - unsigned int i; |
| 154 - EVP_MD_CTX ctx; |
| 155 unsigned char buf[2*EVP_MAX_MD_SIZE]; |
| 156 - unsigned char *q,buf2[12]; |
| 157 - int idx; |
| 158 - long mask; |
| 159 + unsigned char buf2[12]; |
| 160 int err=0; |
| 161 - const EVP_MD *md; |
| 162 + int digests_len; |
| 163 |
| 164 - q=buf; |
| 165 - |
| 166 - if (s->s3->handshake_buffer) |
| 167 + if (s->s3->handshake_buffer) |
| 168 if (!ssl3_digest_cached_records(s)) |
| 169 return 0; |
| 170 |
| 171 - EVP_MD_CTX_init(&ctx); |
| 172 - |
| 173 - for (idx=0;ssl_get_handshake_digest(idx,&mask,&md);idx++) |
| 174 + digests_len = tls1_handshake_digest(s, buf, sizeof(buf)); |
| 175 + if (digests_len < 0) |
| 176 { |
| 177 - if (mask & ssl_get_algorithm2(s)) |
| 178 - { |
| 179 - int hashsize = EVP_MD_size(md); |
| 180 - if (hashsize < 0 || hashsize > (int)(sizeof buf - (size_
t)(q-buf))) |
| 181 - { |
| 182 - /* internal error: 'buf' is too small for this c
ipersuite! */ |
| 183 - err = 1; |
| 184 - } |
| 185 - else |
| 186 - { |
| 187 - EVP_MD_CTX_copy_ex(&ctx,s->s3->handshake_dgst[id
x]); |
| 188 - EVP_DigestFinal_ex(&ctx,q,&i); |
| 189 - if (i != (unsigned int)hashsize) /* can't really
happen */ |
| 190 - err = 1; |
| 191 - q+=i; |
| 192 - } |
| 193 - } |
| 194 + err = 1; |
| 195 + digests_len = 0; |
| 196 } |
| 197 - |
| 198 + |
| 199 if (!tls1_PRF(ssl_get_algorithm2(s), |
| 200 - str,slen, buf,(int)(q-buf), NULL,0, NULL,0, NULL,0, |
| 201 + str,slen, buf, digests_len, NULL,0, NULL,0, NULL,0, |
| 202 s->session->master_key,s->session->master_key_length, |
| 203 out,buf2,sizeof buf2)) |
| 204 err = 1; |
| 205 - EVP_MD_CTX_cleanup(&ctx); |
| 206 |
| 207 if (err) |
| 208 return 0; |
| 209 diff --git a/ssl/t1_lib.c b/ssl/t1_lib.c |
| 210 index ea7fefa..d7ea9a5 100644 |
| 211 --- a/ssl/t1_lib.c |
| 212 +++ b/ssl/t1_lib.c |
| 213 @@ -2684,6 +2684,17 @@ tls1_channel_id_hash(EVP_MD_CTX *md, SSL *s) |
| 214 |
| 215 EVP_DigestUpdate(md, kClientIDMagic, sizeof(kClientIDMagic)); |
| 216 |
| 217 + if (s->hit) |
| 218 + { |
| 219 + static const char kResumptionMagic[] = "Resumption"; |
| 220 + EVP_DigestUpdate(md, kResumptionMagic, |
| 221 + sizeof(kResumptionMagic)); |
| 222 + if (s->session->original_handshake_hash_len == 0) |
| 223 + return 0; |
| 224 + EVP_DigestUpdate(md, s->session->original_handshake_hash, |
| 225 + s->session->original_handshake_hash_len); |
| 226 + } |
| 227 + |
| 228 EVP_MD_CTX_init(&ctx); |
| 229 for (i = 0; i < SSL_MAX_DIGEST; i++) |
| 230 { |
| 231 @@ -2698,3 +2709,29 @@ tls1_channel_id_hash(EVP_MD_CTX *md, SSL *s) |
| 232 return 1; |
| 233 } |
| 234 #endif |
| 235 + |
| 236 +/* tls1_record_handshake_hashes_for_channel_id records the current handshake |
| 237 + * hashes in |s->session| so that Channel ID resumptions can sign that data. */ |
| 238 +int tls1_record_handshake_hashes_for_channel_id(SSL *s) |
| 239 + { |
| 240 + int digest_len; |
| 241 + /* This function should never be called for a resumed session because |
| 242 + * the handshake hashes that we wish to record are for the original, |
| 243 + * full handshake. */ |
| 244 + if (s->hit) |
| 245 + return -1; |
| 246 + /* It only makes sense to call this function if Channel IDs have been |
| 247 + * negotiated. */ |
| 248 + if (!s->s3->tlsext_channel_id_valid) |
| 249 + return -1; |
| 250 + |
| 251 + digest_len = tls1_handshake_digest( |
| 252 + s, s->session->original_handshake_hash, |
| 253 + sizeof(s->session->original_handshake_hash)); |
| 254 + if (digest_len < 0) |
| 255 + return -1; |
| 256 + |
| 257 + s->session->original_handshake_hash_len = digest_len; |
| 258 + |
| 259 + return 1; |
| 260 + } |
| 261 diff --git a/ssl/tls1.h b/ssl/tls1.h |
| 262 index c4f69aa..5559486 100644 |
| 263 --- a/ssl/tls1.h |
| 264 +++ b/ssl/tls1.h |
| 265 @@ -255,7 +255,7 @@ extern "C" { |
| 266 #endif |
| 267 |
| 268 /* This is not an IANA defined extension number */ |
| 269 -#define TLSEXT_TYPE_channel_id 30031 |
| 270 +#define TLSEXT_TYPE_channel_id 30032 |
| 271 |
| 272 /* NameType value from RFC 3546 */ |
| 273 #define TLSEXT_NAMETYPE_host_name 0 |
OLD | NEW |