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 |