/src/hostap/src/tls/tlsv1_server_write.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * TLSv1 server - write handshake message |
3 | | * Copyright (c) 2006-2014, Jouni Malinen <j@w1.fi> |
4 | | * |
5 | | * This software may be distributed under the terms of the BSD license. |
6 | | * See README for more details. |
7 | | */ |
8 | | |
9 | | #include "includes.h" |
10 | | |
11 | | #include "common.h" |
12 | | #include "crypto/md5.h" |
13 | | #include "crypto/sha1.h" |
14 | | #include "crypto/sha256.h" |
15 | | #include "crypto/tls.h" |
16 | | #include "crypto/random.h" |
17 | | #include "x509v3.h" |
18 | | #include "tlsv1_common.h" |
19 | | #include "tlsv1_record.h" |
20 | | #include "tlsv1_server.h" |
21 | | #include "tlsv1_server_i.h" |
22 | | |
23 | | |
24 | | static size_t tls_server_cert_chain_der_len(struct tlsv1_server *conn) |
25 | 0 | { |
26 | 0 | size_t len = 0; |
27 | 0 | struct x509_certificate *cert; |
28 | |
|
29 | 0 | cert = conn->cred ? conn->cred->cert : NULL; |
30 | 0 | while (cert) { |
31 | 0 | len += 3 + cert->cert_len; |
32 | 0 | if (x509_certificate_self_signed(cert)) |
33 | 0 | break; |
34 | 0 | cert = x509_certificate_get_subject(conn->cred->trusted_certs, |
35 | 0 | &cert->issuer); |
36 | 0 | } |
37 | |
|
38 | 0 | return len; |
39 | 0 | } |
40 | | |
41 | | |
42 | | static int tls_write_server_hello(struct tlsv1_server *conn, |
43 | | u8 **msgpos, u8 *end) |
44 | 0 | { |
45 | 0 | u8 *pos, *rhdr, *hs_start, *hs_length, *ext_start; |
46 | 0 | struct os_time now; |
47 | 0 | size_t rlen; |
48 | |
|
49 | 0 | pos = *msgpos; |
50 | |
|
51 | 0 | tlsv1_server_log(conn, "Send ServerHello"); |
52 | 0 | rhdr = pos; |
53 | 0 | pos += TLS_RECORD_HEADER_LEN; |
54 | |
|
55 | 0 | os_get_time(&now); |
56 | 0 | #ifdef TEST_FUZZ |
57 | 0 | now.sec = 0xfffefdfc; |
58 | 0 | #endif /* TEST_FUZZ */ |
59 | 0 | WPA_PUT_BE32(conn->server_random, now.sec); |
60 | 0 | if (random_get_bytes(conn->server_random + 4, TLS_RANDOM_LEN - 4)) { |
61 | 0 | wpa_printf(MSG_ERROR, "TLSv1: Could not generate " |
62 | 0 | "server_random"); |
63 | 0 | return -1; |
64 | 0 | } |
65 | 0 | wpa_hexdump(MSG_MSGDUMP, "TLSv1: server_random", |
66 | 0 | conn->server_random, TLS_RANDOM_LEN); |
67 | |
|
68 | 0 | conn->session_id_len = TLS_SESSION_ID_MAX_LEN; |
69 | 0 | if (random_get_bytes(conn->session_id, conn->session_id_len)) { |
70 | 0 | wpa_printf(MSG_ERROR, "TLSv1: Could not generate " |
71 | 0 | "session_id"); |
72 | 0 | return -1; |
73 | 0 | } |
74 | 0 | wpa_hexdump(MSG_MSGDUMP, "TLSv1: session_id", |
75 | 0 | conn->session_id, conn->session_id_len); |
76 | | |
77 | | /* opaque fragment[TLSPlaintext.length] */ |
78 | | |
79 | | /* Handshake */ |
80 | 0 | hs_start = pos; |
81 | | /* HandshakeType msg_type */ |
82 | 0 | *pos++ = TLS_HANDSHAKE_TYPE_SERVER_HELLO; |
83 | | /* uint24 length (to be filled) */ |
84 | 0 | hs_length = pos; |
85 | 0 | pos += 3; |
86 | | /* body - ServerHello */ |
87 | | /* ProtocolVersion server_version */ |
88 | 0 | WPA_PUT_BE16(pos, conn->rl.tls_version); |
89 | 0 | pos += 2; |
90 | | /* Random random: uint32 gmt_unix_time, opaque random_bytes */ |
91 | 0 | os_memcpy(pos, conn->server_random, TLS_RANDOM_LEN); |
92 | 0 | pos += TLS_RANDOM_LEN; |
93 | | /* SessionID session_id */ |
94 | 0 | *pos++ = conn->session_id_len; |
95 | 0 | os_memcpy(pos, conn->session_id, conn->session_id_len); |
96 | 0 | pos += conn->session_id_len; |
97 | | /* CipherSuite cipher_suite */ |
98 | 0 | WPA_PUT_BE16(pos, conn->cipher_suite); |
99 | 0 | pos += 2; |
100 | | /* CompressionMethod compression_method */ |
101 | 0 | *pos++ = TLS_COMPRESSION_NULL; |
102 | | |
103 | | /* Extension */ |
104 | 0 | ext_start = pos; |
105 | 0 | pos += 2; |
106 | |
|
107 | 0 | if (conn->status_request) { |
108 | | /* Add a status_request extension with empty extension_data */ |
109 | | /* ExtensionsType extension_type = status_request(5) */ |
110 | 0 | WPA_PUT_BE16(pos, TLS_EXT_STATUS_REQUEST); |
111 | 0 | pos += 2; |
112 | | /* opaque extension_data<0..2^16-1> length */ |
113 | 0 | WPA_PUT_BE16(pos, 0); |
114 | 0 | pos += 2; |
115 | 0 | } |
116 | |
|
117 | 0 | if (conn->status_request_v2) { |
118 | | /* |
119 | | Add a status_request_v2 extension with empty extension_data |
120 | | */ |
121 | | /* ExtensionsType extension_type = status_request_v2(17) */ |
122 | 0 | WPA_PUT_BE16(pos, TLS_EXT_STATUS_REQUEST_V2); |
123 | 0 | pos += 2; |
124 | | /* opaque extension_data<0..2^16-1> length */ |
125 | 0 | WPA_PUT_BE16(pos, 0); |
126 | 0 | pos += 2; |
127 | 0 | } |
128 | |
|
129 | 0 | if (conn->session_ticket && conn->session_ticket_cb) { |
130 | 0 | int res = conn->session_ticket_cb( |
131 | 0 | conn->session_ticket_cb_ctx, |
132 | 0 | conn->session_ticket, conn->session_ticket_len, |
133 | 0 | conn->client_random, conn->server_random, |
134 | 0 | conn->master_secret); |
135 | 0 | if (res < 0) { |
136 | 0 | tlsv1_server_log(conn, "SessionTicket callback indicated failure"); |
137 | 0 | tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, |
138 | 0 | TLS_ALERT_HANDSHAKE_FAILURE); |
139 | 0 | return -1; |
140 | 0 | } |
141 | 0 | conn->use_session_ticket = res; |
142 | |
|
143 | 0 | if (conn->use_session_ticket) { |
144 | 0 | if (tlsv1_server_derive_keys(conn, NULL, 0) < 0) { |
145 | 0 | wpa_printf(MSG_DEBUG, "TLSv1: Failed to " |
146 | 0 | "derive keys"); |
147 | 0 | tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, |
148 | 0 | TLS_ALERT_INTERNAL_ERROR); |
149 | 0 | return -1; |
150 | 0 | } |
151 | 0 | } |
152 | | |
153 | | /* |
154 | | * RFC 4507 specifies that server would include an empty |
155 | | * SessionTicket extension in ServerHello and a |
156 | | * NewSessionTicket message after the ServerHello. However, |
157 | | * EAP-FAST (RFC 4851), i.e., the only user of SessionTicket |
158 | | * extension at the moment, does not use such extensions. |
159 | | * |
160 | | * TODO: Add support for configuring RFC 4507 behavior and make |
161 | | * EAP-FAST disable it. |
162 | | */ |
163 | 0 | } |
164 | | |
165 | 0 | if (pos == ext_start + 2) |
166 | 0 | pos -= 2; /* no extensions */ |
167 | 0 | else |
168 | 0 | WPA_PUT_BE16(ext_start, pos - ext_start - 2); |
169 | |
|
170 | 0 | WPA_PUT_BE24(hs_length, pos - hs_length - 3); |
171 | 0 | tls_verify_hash_add(&conn->verify, hs_start, pos - hs_start); |
172 | |
|
173 | 0 | if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_HANDSHAKE, |
174 | 0 | rhdr, end - rhdr, hs_start, pos - hs_start, |
175 | 0 | &rlen) < 0) { |
176 | 0 | wpa_printf(MSG_DEBUG, "TLSv1: Failed to create TLS record"); |
177 | 0 | tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, |
178 | 0 | TLS_ALERT_INTERNAL_ERROR); |
179 | 0 | return -1; |
180 | 0 | } |
181 | 0 | pos = rhdr + rlen; |
182 | |
|
183 | 0 | *msgpos = pos; |
184 | |
|
185 | 0 | return 0; |
186 | 0 | } |
187 | | |
188 | | |
189 | | static int tls_write_server_certificate(struct tlsv1_server *conn, |
190 | | u8 **msgpos, u8 *end) |
191 | 0 | { |
192 | 0 | u8 *pos, *rhdr, *hs_start, *hs_length, *cert_start; |
193 | 0 | size_t rlen; |
194 | 0 | struct x509_certificate *cert; |
195 | 0 | const struct tls_cipher_suite *suite; |
196 | |
|
197 | 0 | suite = tls_get_cipher_suite(conn->rl.cipher_suite); |
198 | 0 | if (suite && suite->key_exchange == TLS_KEY_X_DH_anon) { |
199 | 0 | wpa_printf(MSG_DEBUG, "TLSv1: Do not send Certificate when " |
200 | 0 | "using anonymous DH"); |
201 | 0 | return 0; |
202 | 0 | } |
203 | | |
204 | 0 | pos = *msgpos; |
205 | 0 | if (TLS_RECORD_HEADER_LEN + 1 + 3 + 3 > end - pos) { |
206 | 0 | tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, |
207 | 0 | TLS_ALERT_INTERNAL_ERROR); |
208 | 0 | return -1; |
209 | 0 | } |
210 | | |
211 | 0 | tlsv1_server_log(conn, "Send Certificate"); |
212 | 0 | rhdr = pos; |
213 | 0 | pos += TLS_RECORD_HEADER_LEN; |
214 | | |
215 | | /* opaque fragment[TLSPlaintext.length] */ |
216 | | |
217 | | /* Handshake */ |
218 | 0 | hs_start = pos; |
219 | | /* HandshakeType msg_type */ |
220 | 0 | *pos++ = TLS_HANDSHAKE_TYPE_CERTIFICATE; |
221 | | /* uint24 length (to be filled) */ |
222 | 0 | hs_length = pos; |
223 | 0 | pos += 3; |
224 | | /* body - Certificate */ |
225 | | /* uint24 length (to be filled) */ |
226 | 0 | cert_start = pos; |
227 | 0 | pos += 3; |
228 | 0 | cert = conn->cred->cert; |
229 | 0 | while (cert) { |
230 | 0 | if (3 + cert->cert_len > (size_t) (end - pos)) { |
231 | 0 | wpa_printf(MSG_DEBUG, "TLSv1: Not enough buffer space " |
232 | 0 | "for Certificate (cert_len=%lu left=%lu)", |
233 | 0 | (unsigned long) cert->cert_len, |
234 | 0 | (unsigned long) (end - pos)); |
235 | 0 | tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, |
236 | 0 | TLS_ALERT_INTERNAL_ERROR); |
237 | 0 | return -1; |
238 | 0 | } |
239 | 0 | WPA_PUT_BE24(pos, cert->cert_len); |
240 | 0 | pos += 3; |
241 | 0 | os_memcpy(pos, cert->cert_start, cert->cert_len); |
242 | 0 | pos += cert->cert_len; |
243 | |
|
244 | 0 | if (x509_certificate_self_signed(cert)) |
245 | 0 | break; |
246 | 0 | cert = x509_certificate_get_subject(conn->cred->trusted_certs, |
247 | 0 | &cert->issuer); |
248 | 0 | } |
249 | 0 | if (cert == conn->cred->cert || cert == NULL) { |
250 | | /* |
251 | | * Server was not configured with all the needed certificates |
252 | | * to form a full certificate chain. The client may fail to |
253 | | * validate the chain unless it is configured with all the |
254 | | * missing CA certificates. |
255 | | */ |
256 | 0 | wpa_printf(MSG_DEBUG, "TLSv1: Full server certificate chain " |
257 | 0 | "not configured - validation may fail"); |
258 | 0 | } |
259 | 0 | WPA_PUT_BE24(cert_start, pos - cert_start - 3); |
260 | |
|
261 | 0 | WPA_PUT_BE24(hs_length, pos - hs_length - 3); |
262 | |
|
263 | 0 | if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_HANDSHAKE, |
264 | 0 | rhdr, end - rhdr, hs_start, pos - hs_start, |
265 | 0 | &rlen) < 0) { |
266 | 0 | wpa_printf(MSG_DEBUG, "TLSv1: Failed to generate a record"); |
267 | 0 | tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, |
268 | 0 | TLS_ALERT_INTERNAL_ERROR); |
269 | 0 | return -1; |
270 | 0 | } |
271 | 0 | pos = rhdr + rlen; |
272 | |
|
273 | 0 | tls_verify_hash_add(&conn->verify, hs_start, pos - hs_start); |
274 | |
|
275 | 0 | *msgpos = pos; |
276 | |
|
277 | 0 | return 0; |
278 | 0 | } |
279 | | |
280 | | |
281 | | static int tls_write_server_certificate_status(struct tlsv1_server *conn, |
282 | | u8 **msgpos, u8 *end, |
283 | | int ocsp_multi, |
284 | | char *ocsp_resp, |
285 | | size_t ocsp_resp_len) |
286 | 0 | { |
287 | 0 | u8 *pos, *rhdr, *hs_start, *hs_length; |
288 | 0 | size_t rlen; |
289 | |
|
290 | 0 | if (!ocsp_resp) { |
291 | | /* |
292 | | * Client did not request certificate status or there is no |
293 | | * matching response cached. |
294 | | */ |
295 | 0 | return 0; |
296 | 0 | } |
297 | | |
298 | 0 | pos = *msgpos; |
299 | 0 | if (TLS_RECORD_HEADER_LEN + 1 + 3 + 1 + 3 + ocsp_resp_len > |
300 | 0 | (unsigned int) (end - pos)) { |
301 | 0 | tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, |
302 | 0 | TLS_ALERT_INTERNAL_ERROR); |
303 | 0 | return -1; |
304 | 0 | } |
305 | | |
306 | 0 | tlsv1_server_log(conn, "Send CertificateStatus (multi=%d)", ocsp_multi); |
307 | 0 | rhdr = pos; |
308 | 0 | pos += TLS_RECORD_HEADER_LEN; |
309 | | |
310 | | /* opaque fragment[TLSPlaintext.length] */ |
311 | | |
312 | | /* Handshake */ |
313 | 0 | hs_start = pos; |
314 | | /* HandshakeType msg_type */ |
315 | 0 | *pos++ = TLS_HANDSHAKE_TYPE_CERTIFICATE_STATUS; |
316 | | /* uint24 length (to be filled) */ |
317 | 0 | hs_length = pos; |
318 | 0 | pos += 3; |
319 | | |
320 | | /* body - CertificateStatus |
321 | | * |
322 | | * struct { |
323 | | * CertificateStatusType status_type; |
324 | | * select (status_type) { |
325 | | * case ocsp: OCSPResponse; |
326 | | * case ocsp_multi: OCSPResponseList; |
327 | | * } response; |
328 | | * } CertificateStatus; |
329 | | * |
330 | | * opaque OCSPResponse<1..2^24-1>; |
331 | | * |
332 | | * struct { |
333 | | * OCSPResponse ocsp_response_list<1..2^24-1>; |
334 | | * } OCSPResponseList; |
335 | | */ |
336 | | |
337 | | /* CertificateStatusType status_type */ |
338 | 0 | if (ocsp_multi) |
339 | 0 | *pos++ = 2; /* ocsp_multi(2) */ |
340 | 0 | else |
341 | 0 | *pos++ = 1; /* ocsp(1) */ |
342 | | /* uint24 length of OCSPResponse */ |
343 | 0 | WPA_PUT_BE24(pos, ocsp_resp_len); |
344 | 0 | pos += 3; |
345 | 0 | os_memcpy(pos, ocsp_resp, ocsp_resp_len); |
346 | 0 | pos += ocsp_resp_len; |
347 | |
|
348 | 0 | WPA_PUT_BE24(hs_length, pos - hs_length - 3); |
349 | |
|
350 | 0 | if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_HANDSHAKE, |
351 | 0 | rhdr, end - rhdr, hs_start, pos - hs_start, |
352 | 0 | &rlen) < 0) { |
353 | 0 | wpa_printf(MSG_DEBUG, "TLSv1: Failed to generate a record"); |
354 | 0 | tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, |
355 | 0 | TLS_ALERT_INTERNAL_ERROR); |
356 | 0 | return -1; |
357 | 0 | } |
358 | 0 | pos = rhdr + rlen; |
359 | |
|
360 | 0 | tls_verify_hash_add(&conn->verify, hs_start, pos - hs_start); |
361 | |
|
362 | 0 | *msgpos = pos; |
363 | |
|
364 | 0 | return 0; |
365 | 0 | } |
366 | | |
367 | | |
368 | | static int tls_write_server_key_exchange(struct tlsv1_server *conn, |
369 | | u8 **msgpos, u8 *end) |
370 | 0 | { |
371 | 0 | tls_key_exchange keyx; |
372 | 0 | const struct tls_cipher_suite *suite; |
373 | 0 | u8 *pos, *rhdr, *hs_start, *hs_length, *server_params; |
374 | 0 | size_t rlen; |
375 | 0 | u8 *dh_ys; |
376 | 0 | size_t dh_ys_len; |
377 | 0 | const u8 *dh_p; |
378 | 0 | size_t dh_p_len; |
379 | |
|
380 | 0 | suite = tls_get_cipher_suite(conn->rl.cipher_suite); |
381 | 0 | if (suite == NULL) |
382 | 0 | keyx = TLS_KEY_X_NULL; |
383 | 0 | else |
384 | 0 | keyx = suite->key_exchange; |
385 | |
|
386 | 0 | if (!tls_server_key_exchange_allowed(conn->rl.cipher_suite)) { |
387 | 0 | wpa_printf(MSG_DEBUG, "TLSv1: No ServerKeyExchange needed"); |
388 | 0 | return 0; |
389 | 0 | } |
390 | | |
391 | 0 | if (keyx != TLS_KEY_X_DH_anon && keyx != TLS_KEY_X_DHE_RSA) { |
392 | 0 | wpa_printf(MSG_DEBUG, "TLSv1: ServerKeyExchange not yet " |
393 | 0 | "supported with key exchange type %d", keyx); |
394 | 0 | return -1; |
395 | 0 | } |
396 | | |
397 | 0 | if (conn->cred == NULL || conn->cred->dh_p == NULL || |
398 | 0 | conn->cred->dh_g == NULL) { |
399 | 0 | wpa_printf(MSG_DEBUG, "TLSv1: No DH parameters available for " |
400 | 0 | "ServerKeyExhcange"); |
401 | 0 | return -1; |
402 | 0 | } |
403 | | |
404 | 0 | tlsv1_server_get_dh_p(conn, &dh_p, &dh_p_len); |
405 | |
|
406 | 0 | os_free(conn->dh_secret); |
407 | 0 | conn->dh_secret_len = dh_p_len; |
408 | 0 | conn->dh_secret = os_malloc(conn->dh_secret_len); |
409 | 0 | if (conn->dh_secret == NULL) { |
410 | 0 | wpa_printf(MSG_DEBUG, "TLSv1: Failed to allocate " |
411 | 0 | "memory for secret (Diffie-Hellman)"); |
412 | 0 | tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, |
413 | 0 | TLS_ALERT_INTERNAL_ERROR); |
414 | 0 | return -1; |
415 | 0 | } |
416 | 0 | if (random_get_bytes(conn->dh_secret, conn->dh_secret_len)) { |
417 | 0 | wpa_printf(MSG_DEBUG, "TLSv1: Failed to get random " |
418 | 0 | "data for Diffie-Hellman"); |
419 | 0 | tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, |
420 | 0 | TLS_ALERT_INTERNAL_ERROR); |
421 | 0 | os_free(conn->dh_secret); |
422 | 0 | conn->dh_secret = NULL; |
423 | 0 | return -1; |
424 | 0 | } |
425 | | |
426 | 0 | if (os_memcmp(conn->dh_secret, dh_p, conn->dh_secret_len) > 0) |
427 | 0 | conn->dh_secret[0] = 0; /* make sure secret < p */ |
428 | |
|
429 | 0 | pos = conn->dh_secret; |
430 | 0 | while (pos + 1 < conn->dh_secret + conn->dh_secret_len && *pos == 0) |
431 | 0 | pos++; |
432 | 0 | if (pos != conn->dh_secret) { |
433 | 0 | os_memmove(conn->dh_secret, pos, |
434 | 0 | conn->dh_secret_len - (pos - conn->dh_secret)); |
435 | 0 | conn->dh_secret_len -= pos - conn->dh_secret; |
436 | 0 | } |
437 | 0 | wpa_hexdump_key(MSG_DEBUG, "TLSv1: DH server's secret value", |
438 | 0 | conn->dh_secret, conn->dh_secret_len); |
439 | | |
440 | | /* Ys = g^secret mod p */ |
441 | 0 | dh_ys_len = dh_p_len; |
442 | 0 | dh_ys = os_malloc(dh_ys_len); |
443 | 0 | if (dh_ys == NULL) { |
444 | 0 | wpa_printf(MSG_DEBUG, "TLSv1: Failed to allocate memory for " |
445 | 0 | "Diffie-Hellman"); |
446 | 0 | tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, |
447 | 0 | TLS_ALERT_INTERNAL_ERROR); |
448 | 0 | return -1; |
449 | 0 | } |
450 | 0 | if (crypto_mod_exp(conn->cred->dh_g, conn->cred->dh_g_len, |
451 | 0 | conn->dh_secret, conn->dh_secret_len, |
452 | 0 | dh_p, dh_p_len, dh_ys, &dh_ys_len)) { |
453 | 0 | tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, |
454 | 0 | TLS_ALERT_INTERNAL_ERROR); |
455 | 0 | os_free(dh_ys); |
456 | 0 | return -1; |
457 | 0 | } |
458 | | |
459 | 0 | wpa_hexdump(MSG_DEBUG, "TLSv1: DH Ys (server's public value)", |
460 | 0 | dh_ys, dh_ys_len); |
461 | | |
462 | | /* |
463 | | * struct { |
464 | | * select (KeyExchangeAlgorithm) { |
465 | | * case diffie_hellman: |
466 | | * ServerDHParams params; |
467 | | * Signature signed_params; |
468 | | * case rsa: |
469 | | * ServerRSAParams params; |
470 | | * Signature signed_params; |
471 | | * }; |
472 | | * } ServerKeyExchange; |
473 | | * |
474 | | * struct { |
475 | | * opaque dh_p<1..2^16-1>; |
476 | | * opaque dh_g<1..2^16-1>; |
477 | | * opaque dh_Ys<1..2^16-1>; |
478 | | * } ServerDHParams; |
479 | | */ |
480 | |
|
481 | 0 | pos = *msgpos; |
482 | |
|
483 | 0 | tlsv1_server_log(conn, "Send ServerKeyExchange"); |
484 | 0 | rhdr = pos; |
485 | 0 | pos += TLS_RECORD_HEADER_LEN; |
486 | | |
487 | | /* opaque fragment[TLSPlaintext.length] */ |
488 | | |
489 | | /* Handshake */ |
490 | 0 | hs_start = pos; |
491 | | /* HandshakeType msg_type */ |
492 | 0 | *pos++ = TLS_HANDSHAKE_TYPE_SERVER_KEY_EXCHANGE; |
493 | | /* uint24 length (to be filled) */ |
494 | 0 | hs_length = pos; |
495 | 0 | pos += 3; |
496 | | |
497 | | /* body - ServerDHParams */ |
498 | 0 | server_params = pos; |
499 | | /* dh_p */ |
500 | 0 | if (2 + dh_p_len > (size_t) (end - pos)) { |
501 | 0 | wpa_printf(MSG_DEBUG, "TLSv1: Not enough buffer space for " |
502 | 0 | "dh_p"); |
503 | 0 | tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, |
504 | 0 | TLS_ALERT_INTERNAL_ERROR); |
505 | 0 | os_free(dh_ys); |
506 | 0 | return -1; |
507 | 0 | } |
508 | 0 | WPA_PUT_BE16(pos, dh_p_len); |
509 | 0 | pos += 2; |
510 | 0 | os_memcpy(pos, dh_p, dh_p_len); |
511 | 0 | pos += dh_p_len; |
512 | | |
513 | | /* dh_g */ |
514 | 0 | if (2 + conn->cred->dh_g_len > (size_t) (end - pos)) { |
515 | 0 | wpa_printf(MSG_DEBUG, "TLSv1: Not enough buffer space for " |
516 | 0 | "dh_g"); |
517 | 0 | tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, |
518 | 0 | TLS_ALERT_INTERNAL_ERROR); |
519 | 0 | os_free(dh_ys); |
520 | 0 | return -1; |
521 | 0 | } |
522 | 0 | WPA_PUT_BE16(pos, conn->cred->dh_g_len); |
523 | 0 | pos += 2; |
524 | 0 | os_memcpy(pos, conn->cred->dh_g, conn->cred->dh_g_len); |
525 | 0 | pos += conn->cred->dh_g_len; |
526 | | |
527 | | /* dh_Ys */ |
528 | 0 | if (2 + dh_ys_len > (size_t) (end - pos)) { |
529 | 0 | wpa_printf(MSG_DEBUG, "TLSv1: Not enough buffer space for " |
530 | 0 | "dh_Ys"); |
531 | 0 | tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, |
532 | 0 | TLS_ALERT_INTERNAL_ERROR); |
533 | 0 | os_free(dh_ys); |
534 | 0 | return -1; |
535 | 0 | } |
536 | 0 | WPA_PUT_BE16(pos, dh_ys_len); |
537 | 0 | pos += 2; |
538 | 0 | os_memcpy(pos, dh_ys, dh_ys_len); |
539 | 0 | pos += dh_ys_len; |
540 | 0 | os_free(dh_ys); |
541 | | |
542 | | /* |
543 | | * select (SignatureAlgorithm) |
544 | | * { case anonymous: struct { }; |
545 | | * case rsa: |
546 | | * digitally-signed struct { |
547 | | * opaque md5_hash[16]; |
548 | | * opaque sha_hash[20]; |
549 | | * }; |
550 | | * case dsa: |
551 | | * digitally-signed struct { |
552 | | * opaque sha_hash[20]; |
553 | | * }; |
554 | | * } Signature; |
555 | | * |
556 | | * md5_hash |
557 | | * MD5(ClientHello.random + ServerHello.random + ServerParams); |
558 | | * |
559 | | * sha_hash |
560 | | * SHA(ClientHello.random + ServerHello.random + ServerParams); |
561 | | */ |
562 | |
|
563 | 0 | if (keyx == TLS_KEY_X_DHE_RSA) { |
564 | 0 | u8 hash[100]; |
565 | 0 | u8 *signed_start; |
566 | 0 | size_t clen; |
567 | 0 | int hlen; |
568 | |
|
569 | 0 | if (conn->rl.tls_version >= TLS_VERSION_1_2) { |
570 | 0 | #ifdef CONFIG_TLSV12 |
571 | 0 | hlen = tlsv12_key_x_server_params_hash( |
572 | 0 | conn->rl.tls_version, TLS_HASH_ALG_SHA256, |
573 | 0 | conn->client_random, |
574 | 0 | conn->server_random, server_params, |
575 | 0 | pos - server_params, hash + 19); |
576 | | |
577 | | /* |
578 | | * RFC 5246, 4.7: |
579 | | * TLS v1.2 adds explicit indication of the used |
580 | | * signature and hash algorithms. |
581 | | * |
582 | | * struct { |
583 | | * HashAlgorithm hash; |
584 | | * SignatureAlgorithm signature; |
585 | | * } SignatureAndHashAlgorithm; |
586 | | */ |
587 | 0 | if (hlen < 0 || end - pos < 2) { |
588 | 0 | tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, |
589 | 0 | TLS_ALERT_INTERNAL_ERROR); |
590 | 0 | return -1; |
591 | 0 | } |
592 | 0 | *pos++ = TLS_HASH_ALG_SHA256; |
593 | 0 | *pos++ = TLS_SIGN_ALG_RSA; |
594 | | |
595 | | /* |
596 | | * RFC 3447, A.2.4 RSASSA-PKCS1-v1_5 |
597 | | * |
598 | | * DigestInfo ::= SEQUENCE { |
599 | | * digestAlgorithm DigestAlgorithm, |
600 | | * digest OCTET STRING |
601 | | * } |
602 | | * |
603 | | * SHA-256 OID: sha256WithRSAEncryption ::= {pkcs-1 11} |
604 | | * |
605 | | * DER encoded DigestInfo for SHA256 per RFC 3447: |
606 | | * 30 31 30 0d 06 09 60 86 48 01 65 03 04 02 01 05 00 |
607 | | * 04 20 || H |
608 | | */ |
609 | 0 | hlen += 19; |
610 | 0 | os_memcpy(hash, |
611 | 0 | "\x30\x31\x30\x0d\x06\x09\x60\x86\x48\x01\x65" |
612 | 0 | "\x03\x04\x02\x01\x05\x00\x04\x20", 19); |
613 | |
|
614 | | #else /* CONFIG_TLSV12 */ |
615 | | tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, |
616 | | TLS_ALERT_INTERNAL_ERROR); |
617 | | return -1; |
618 | | #endif /* CONFIG_TLSV12 */ |
619 | 0 | } else { |
620 | 0 | hlen = tls_key_x_server_params_hash( |
621 | 0 | conn->rl.tls_version, conn->client_random, |
622 | 0 | conn->server_random, server_params, |
623 | 0 | pos - server_params, hash, sizeof(hash)); |
624 | 0 | } |
625 | | |
626 | 0 | if (hlen < 0) { |
627 | 0 | tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, |
628 | 0 | TLS_ALERT_INTERNAL_ERROR); |
629 | 0 | return -1; |
630 | 0 | } |
631 | | |
632 | 0 | wpa_hexdump(MSG_MSGDUMP, "TLS: ServerKeyExchange signed_params hash", |
633 | 0 | hash, hlen); |
634 | | #ifdef CONFIG_TESTING_OPTIONS |
635 | | if (conn->test_flags & TLS_BREAK_SRV_KEY_X_HASH) { |
636 | | tlsv1_server_log(conn, "TESTING: Break ServerKeyExchange signed params hash"); |
637 | | hash[hlen - 1] ^= 0x80; |
638 | | } |
639 | | #endif /* CONFIG_TESTING_OPTIONS */ |
640 | | |
641 | | /* |
642 | | * RFC 2246, 4.7: |
643 | | * In digital signing, one-way hash functions are used as input |
644 | | * for a signing algorithm. A digitally-signed element is |
645 | | * encoded as an opaque vector <0..2^16-1>, where the length is |
646 | | * specified by the signing algorithm and key. |
647 | | * |
648 | | * In RSA signing, a 36-byte structure of two hashes (one SHA |
649 | | * and one MD5) is signed (encrypted with the private key). It |
650 | | * is encoded with PKCS #1 block type 0 or type 1 as described |
651 | | * in [PKCS1]. |
652 | | */ |
653 | 0 | signed_start = pos; /* length to be filled */ |
654 | 0 | pos += 2; |
655 | 0 | clen = end - pos; |
656 | 0 | if (conn->cred == NULL || |
657 | 0 | crypto_private_key_sign_pkcs1(conn->cred->key, hash, hlen, |
658 | 0 | pos, &clen) < 0) { |
659 | 0 | wpa_printf(MSG_DEBUG, "TLSv1: Failed to sign hash (PKCS #1)"); |
660 | 0 | tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, |
661 | 0 | TLS_ALERT_INTERNAL_ERROR); |
662 | 0 | return -1; |
663 | 0 | } |
664 | 0 | WPA_PUT_BE16(signed_start, clen); |
665 | | #ifdef CONFIG_TESTING_OPTIONS |
666 | | if (conn->test_flags & TLS_BREAK_SRV_KEY_X_SIGNATURE) { |
667 | | tlsv1_server_log(conn, "TESTING: Break ServerKeyExchange signed params signature"); |
668 | | pos[clen - 1] ^= 0x80; |
669 | | } |
670 | | #endif /* CONFIG_TESTING_OPTIONS */ |
671 | |
|
672 | 0 | pos += clen; |
673 | 0 | } |
674 | | |
675 | 0 | WPA_PUT_BE24(hs_length, pos - hs_length - 3); |
676 | |
|
677 | 0 | if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_HANDSHAKE, |
678 | 0 | rhdr, end - rhdr, hs_start, pos - hs_start, |
679 | 0 | &rlen) < 0) { |
680 | 0 | wpa_printf(MSG_DEBUG, "TLSv1: Failed to generate a record"); |
681 | 0 | tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, |
682 | 0 | TLS_ALERT_INTERNAL_ERROR); |
683 | 0 | return -1; |
684 | 0 | } |
685 | 0 | pos = rhdr + rlen; |
686 | |
|
687 | 0 | tls_verify_hash_add(&conn->verify, hs_start, pos - hs_start); |
688 | |
|
689 | 0 | *msgpos = pos; |
690 | |
|
691 | 0 | return 0; |
692 | 0 | } |
693 | | |
694 | | |
695 | | static int tls_write_server_certificate_request(struct tlsv1_server *conn, |
696 | | u8 **msgpos, u8 *end) |
697 | 0 | { |
698 | 0 | u8 *pos, *rhdr, *hs_start, *hs_length; |
699 | 0 | size_t rlen; |
700 | |
|
701 | 0 | if (!conn->verify_peer) { |
702 | 0 | wpa_printf(MSG_DEBUG, "TLSv1: No CertificateRequest needed"); |
703 | 0 | return 0; |
704 | 0 | } |
705 | | |
706 | 0 | pos = *msgpos; |
707 | |
|
708 | 0 | tlsv1_server_log(conn, "Send CertificateRequest"); |
709 | 0 | rhdr = pos; |
710 | 0 | pos += TLS_RECORD_HEADER_LEN; |
711 | | |
712 | | /* opaque fragment[TLSPlaintext.length] */ |
713 | | |
714 | | /* Handshake */ |
715 | 0 | hs_start = pos; |
716 | | /* HandshakeType msg_type */ |
717 | 0 | *pos++ = TLS_HANDSHAKE_TYPE_CERTIFICATE_REQUEST; |
718 | | /* uint24 length (to be filled) */ |
719 | 0 | hs_length = pos; |
720 | 0 | pos += 3; |
721 | | /* body - CertificateRequest */ |
722 | | |
723 | | /* |
724 | | * enum { |
725 | | * rsa_sign(1), dss_sign(2), rsa_fixed_dh(3), dss_fixed_dh(4), |
726 | | * (255) |
727 | | * } ClientCertificateType; |
728 | | * ClientCertificateType certificate_types<1..2^8-1> |
729 | | */ |
730 | 0 | *pos++ = 1; |
731 | 0 | *pos++ = 1; /* rsa_sign */ |
732 | | |
733 | | /* |
734 | | * opaque DistinguishedName<1..2^16-1> |
735 | | * DistinguishedName certificate_authorities<3..2^16-1> |
736 | | */ |
737 | | /* TODO: add support for listing DNs for trusted CAs */ |
738 | 0 | WPA_PUT_BE16(pos, 0); |
739 | 0 | pos += 2; |
740 | |
|
741 | 0 | WPA_PUT_BE24(hs_length, pos - hs_length - 3); |
742 | |
|
743 | 0 | if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_HANDSHAKE, |
744 | 0 | rhdr, end - rhdr, hs_start, pos - hs_start, |
745 | 0 | &rlen) < 0) { |
746 | 0 | wpa_printf(MSG_DEBUG, "TLSv1: Failed to generate a record"); |
747 | 0 | tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, |
748 | 0 | TLS_ALERT_INTERNAL_ERROR); |
749 | 0 | return -1; |
750 | 0 | } |
751 | 0 | pos = rhdr + rlen; |
752 | |
|
753 | 0 | tls_verify_hash_add(&conn->verify, hs_start, pos - hs_start); |
754 | |
|
755 | 0 | *msgpos = pos; |
756 | |
|
757 | 0 | return 0; |
758 | 0 | } |
759 | | |
760 | | |
761 | | static int tls_write_server_hello_done(struct tlsv1_server *conn, |
762 | | u8 **msgpos, u8 *end) |
763 | 0 | { |
764 | 0 | u8 *pos; |
765 | 0 | size_t rlen; |
766 | 0 | u8 payload[4]; |
767 | |
|
768 | 0 | tlsv1_server_log(conn, "Send ServerHelloDone"); |
769 | | |
770 | | /* opaque fragment[TLSPlaintext.length] */ |
771 | | |
772 | | /* Handshake */ |
773 | 0 | pos = payload; |
774 | | /* HandshakeType msg_type */ |
775 | 0 | *pos++ = TLS_HANDSHAKE_TYPE_SERVER_HELLO_DONE; |
776 | | /* uint24 length */ |
777 | 0 | WPA_PUT_BE24(pos, 0); |
778 | 0 | pos += 3; |
779 | | /* body - ServerHelloDone (empty) */ |
780 | |
|
781 | 0 | if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_HANDSHAKE, |
782 | 0 | *msgpos, end - *msgpos, payload, pos - payload, |
783 | 0 | &rlen) < 0) { |
784 | 0 | wpa_printf(MSG_DEBUG, "TLSv1: Failed to generate a record"); |
785 | 0 | tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, |
786 | 0 | TLS_ALERT_INTERNAL_ERROR); |
787 | 0 | return -1; |
788 | 0 | } |
789 | | |
790 | 0 | tls_verify_hash_add(&conn->verify, payload, pos - payload); |
791 | |
|
792 | 0 | *msgpos += rlen; |
793 | |
|
794 | 0 | return 0; |
795 | 0 | } |
796 | | |
797 | | |
798 | | static int tls_write_server_change_cipher_spec(struct tlsv1_server *conn, |
799 | | u8 **msgpos, u8 *end) |
800 | 0 | { |
801 | 0 | size_t rlen; |
802 | 0 | u8 payload[1]; |
803 | |
|
804 | 0 | tlsv1_server_log(conn, "Send ChangeCipherSpec"); |
805 | |
|
806 | 0 | payload[0] = TLS_CHANGE_CIPHER_SPEC; |
807 | |
|
808 | 0 | if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_CHANGE_CIPHER_SPEC, |
809 | 0 | *msgpos, end - *msgpos, payload, sizeof(payload), |
810 | 0 | &rlen) < 0) { |
811 | 0 | wpa_printf(MSG_DEBUG, "TLSv1: Failed to create a record"); |
812 | 0 | tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, |
813 | 0 | TLS_ALERT_INTERNAL_ERROR); |
814 | 0 | return -1; |
815 | 0 | } |
816 | | |
817 | 0 | if (tlsv1_record_change_write_cipher(&conn->rl) < 0) { |
818 | 0 | wpa_printf(MSG_DEBUG, "TLSv1: Failed to set write cipher for " |
819 | 0 | "record layer"); |
820 | 0 | tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, |
821 | 0 | TLS_ALERT_INTERNAL_ERROR); |
822 | 0 | return -1; |
823 | 0 | } |
824 | | |
825 | 0 | *msgpos += rlen; |
826 | |
|
827 | 0 | return 0; |
828 | 0 | } |
829 | | |
830 | | |
831 | | static int tls_write_server_finished(struct tlsv1_server *conn, |
832 | | u8 **msgpos, u8 *end) |
833 | 0 | { |
834 | 0 | u8 *pos, *hs_start; |
835 | 0 | size_t rlen, hlen; |
836 | 0 | u8 verify_data[1 + 3 + TLS_VERIFY_DATA_LEN]; |
837 | 0 | u8 hash[MD5_MAC_LEN + SHA1_MAC_LEN]; |
838 | |
|
839 | 0 | pos = *msgpos; |
840 | |
|
841 | 0 | tlsv1_server_log(conn, "Send Finished"); |
842 | | |
843 | | /* Encrypted Handshake Message: Finished */ |
844 | |
|
845 | 0 | #ifdef CONFIG_TLSV12 |
846 | 0 | if (conn->rl.tls_version >= TLS_VERSION_1_2) { |
847 | 0 | hlen = SHA256_MAC_LEN; |
848 | 0 | if (conn->verify.sha256_server == NULL || |
849 | 0 | crypto_hash_finish(conn->verify.sha256_server, hash, &hlen) |
850 | 0 | < 0) { |
851 | 0 | conn->verify.sha256_server = NULL; |
852 | 0 | tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, |
853 | 0 | TLS_ALERT_INTERNAL_ERROR); |
854 | 0 | return -1; |
855 | 0 | } |
856 | 0 | conn->verify.sha256_server = NULL; |
857 | 0 | } else { |
858 | 0 | #endif /* CONFIG_TLSV12 */ |
859 | |
|
860 | 0 | hlen = MD5_MAC_LEN; |
861 | 0 | if (conn->verify.md5_server == NULL || |
862 | 0 | crypto_hash_finish(conn->verify.md5_server, hash, &hlen) < 0) { |
863 | 0 | tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, |
864 | 0 | TLS_ALERT_INTERNAL_ERROR); |
865 | 0 | conn->verify.md5_server = NULL; |
866 | 0 | crypto_hash_finish(conn->verify.sha1_server, NULL, NULL); |
867 | 0 | conn->verify.sha1_server = NULL; |
868 | 0 | return -1; |
869 | 0 | } |
870 | 0 | conn->verify.md5_server = NULL; |
871 | 0 | hlen = SHA1_MAC_LEN; |
872 | 0 | if (conn->verify.sha1_server == NULL || |
873 | 0 | crypto_hash_finish(conn->verify.sha1_server, hash + MD5_MAC_LEN, |
874 | 0 | &hlen) < 0) { |
875 | 0 | conn->verify.sha1_server = NULL; |
876 | 0 | tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, |
877 | 0 | TLS_ALERT_INTERNAL_ERROR); |
878 | 0 | return -1; |
879 | 0 | } |
880 | 0 | conn->verify.sha1_server = NULL; |
881 | 0 | hlen = MD5_MAC_LEN + SHA1_MAC_LEN; |
882 | |
|
883 | 0 | #ifdef CONFIG_TLSV12 |
884 | 0 | } |
885 | 0 | #endif /* CONFIG_TLSV12 */ |
886 | | |
887 | 0 | if (tls_prf(conn->rl.tls_version, |
888 | 0 | conn->master_secret, TLS_MASTER_SECRET_LEN, |
889 | 0 | "server finished", hash, hlen, |
890 | 0 | verify_data + 1 + 3, TLS_VERIFY_DATA_LEN)) { |
891 | 0 | wpa_printf(MSG_DEBUG, "TLSv1: Failed to generate verify_data"); |
892 | 0 | tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, |
893 | 0 | TLS_ALERT_INTERNAL_ERROR); |
894 | 0 | return -1; |
895 | 0 | } |
896 | 0 | wpa_hexdump_key(MSG_DEBUG, "TLSv1: verify_data (server)", |
897 | 0 | verify_data + 1 + 3, TLS_VERIFY_DATA_LEN); |
898 | | #ifdef CONFIG_TESTING_OPTIONS |
899 | | if (conn->test_flags & TLS_BREAK_VERIFY_DATA) { |
900 | | tlsv1_server_log(conn, "TESTING: Break verify_data (server)"); |
901 | | verify_data[1 + 3 + 1] ^= 0x80; |
902 | | } |
903 | | #endif /* CONFIG_TESTING_OPTIONS */ |
904 | | |
905 | | /* Handshake */ |
906 | 0 | pos = hs_start = verify_data; |
907 | | /* HandshakeType msg_type */ |
908 | 0 | *pos++ = TLS_HANDSHAKE_TYPE_FINISHED; |
909 | | /* uint24 length */ |
910 | 0 | WPA_PUT_BE24(pos, TLS_VERIFY_DATA_LEN); |
911 | 0 | pos += 3; |
912 | 0 | pos += TLS_VERIFY_DATA_LEN; |
913 | 0 | tls_verify_hash_add(&conn->verify, hs_start, pos - hs_start); |
914 | |
|
915 | 0 | if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_HANDSHAKE, |
916 | 0 | *msgpos, end - *msgpos, hs_start, pos - hs_start, |
917 | 0 | &rlen) < 0) { |
918 | 0 | wpa_printf(MSG_DEBUG, "TLSv1: Failed to create a record"); |
919 | 0 | tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, |
920 | 0 | TLS_ALERT_INTERNAL_ERROR); |
921 | 0 | return -1; |
922 | 0 | } |
923 | | |
924 | 0 | *msgpos += rlen; |
925 | |
|
926 | 0 | return 0; |
927 | 0 | } |
928 | | |
929 | | |
930 | | static u8 * tls_send_server_hello(struct tlsv1_server *conn, size_t *out_len) |
931 | 0 | { |
932 | 0 | u8 *msg, *end, *pos; |
933 | 0 | size_t msglen; |
934 | 0 | int ocsp_multi = 0; |
935 | 0 | char *ocsp_resp = NULL; |
936 | 0 | size_t ocsp_resp_len = 0; |
937 | |
|
938 | 0 | *out_len = 0; |
939 | |
|
940 | 0 | if (conn->status_request_multi && |
941 | 0 | conn->cred->ocsp_stapling_response_multi) { |
942 | 0 | ocsp_resp = os_readfile( |
943 | 0 | conn->cred->ocsp_stapling_response_multi, |
944 | 0 | &ocsp_resp_len); |
945 | 0 | ocsp_multi = 1; |
946 | 0 | } else if ((conn->status_request || conn->status_request_v2) && |
947 | 0 | conn->cred->ocsp_stapling_response) { |
948 | 0 | ocsp_resp = os_readfile(conn->cred->ocsp_stapling_response, |
949 | 0 | &ocsp_resp_len); |
950 | 0 | } |
951 | 0 | if (!ocsp_resp) |
952 | 0 | ocsp_resp_len = 0; |
953 | |
|
954 | 0 | msglen = 1000 + tls_server_cert_chain_der_len(conn) + ocsp_resp_len; |
955 | |
|
956 | 0 | msg = os_malloc(msglen); |
957 | 0 | if (msg == NULL) { |
958 | 0 | os_free(ocsp_resp); |
959 | 0 | return NULL; |
960 | 0 | } |
961 | | |
962 | 0 | pos = msg; |
963 | 0 | end = msg + msglen; |
964 | |
|
965 | 0 | if (tls_write_server_hello(conn, &pos, end) < 0) { |
966 | 0 | os_free(msg); |
967 | 0 | os_free(ocsp_resp); |
968 | 0 | return NULL; |
969 | 0 | } |
970 | | |
971 | 0 | if (conn->use_session_ticket) { |
972 | 0 | os_free(ocsp_resp); |
973 | | |
974 | | /* Abbreviated handshake using session ticket; RFC 4507 */ |
975 | 0 | if (tls_write_server_change_cipher_spec(conn, &pos, end) < 0 || |
976 | 0 | tls_write_server_finished(conn, &pos, end) < 0) { |
977 | 0 | os_free(msg); |
978 | 0 | return NULL; |
979 | 0 | } |
980 | | |
981 | 0 | *out_len = pos - msg; |
982 | |
|
983 | 0 | conn->state = CHANGE_CIPHER_SPEC; |
984 | |
|
985 | 0 | return msg; |
986 | 0 | } |
987 | | |
988 | | /* Full handshake */ |
989 | 0 | if (tls_write_server_certificate(conn, &pos, end) < 0 || |
990 | 0 | tls_write_server_certificate_status(conn, &pos, end, ocsp_multi, |
991 | 0 | ocsp_resp, ocsp_resp_len) < 0 || |
992 | 0 | tls_write_server_key_exchange(conn, &pos, end) < 0 || |
993 | 0 | tls_write_server_certificate_request(conn, &pos, end) < 0 || |
994 | 0 | tls_write_server_hello_done(conn, &pos, end) < 0) { |
995 | 0 | os_free(msg); |
996 | 0 | os_free(ocsp_resp); |
997 | 0 | return NULL; |
998 | 0 | } |
999 | 0 | os_free(ocsp_resp); |
1000 | |
|
1001 | 0 | *out_len = pos - msg; |
1002 | |
|
1003 | 0 | conn->state = CLIENT_CERTIFICATE; |
1004 | |
|
1005 | 0 | return msg; |
1006 | 0 | } |
1007 | | |
1008 | | |
1009 | | static u8 * tls_send_change_cipher_spec(struct tlsv1_server *conn, |
1010 | | size_t *out_len) |
1011 | 0 | { |
1012 | 0 | u8 *msg, *end, *pos; |
1013 | |
|
1014 | 0 | *out_len = 0; |
1015 | |
|
1016 | 0 | msg = os_malloc(1000); |
1017 | 0 | if (msg == NULL) |
1018 | 0 | return NULL; |
1019 | | |
1020 | 0 | pos = msg; |
1021 | 0 | end = msg + 1000; |
1022 | |
|
1023 | 0 | if (tls_write_server_change_cipher_spec(conn, &pos, end) < 0 || |
1024 | 0 | tls_write_server_finished(conn, &pos, end) < 0) { |
1025 | 0 | os_free(msg); |
1026 | 0 | return NULL; |
1027 | 0 | } |
1028 | | |
1029 | 0 | *out_len = pos - msg; |
1030 | |
|
1031 | 0 | tlsv1_server_log(conn, "Handshake completed successfully"); |
1032 | 0 | conn->state = ESTABLISHED; |
1033 | |
|
1034 | 0 | return msg; |
1035 | 0 | } |
1036 | | |
1037 | | |
1038 | | u8 * tlsv1_server_handshake_write(struct tlsv1_server *conn, size_t *out_len) |
1039 | 0 | { |
1040 | 0 | switch (conn->state) { |
1041 | 0 | case SERVER_HELLO: |
1042 | 0 | return tls_send_server_hello(conn, out_len); |
1043 | 0 | case SERVER_CHANGE_CIPHER_SPEC: |
1044 | 0 | return tls_send_change_cipher_spec(conn, out_len); |
1045 | 0 | default: |
1046 | 0 | if (conn->state == ESTABLISHED && conn->use_session_ticket) { |
1047 | | /* Abbreviated handshake was already completed. */ |
1048 | 0 | return NULL; |
1049 | 0 | } |
1050 | 0 | tlsv1_server_log(conn, "Unexpected state %d while generating reply", |
1051 | 0 | conn->state); |
1052 | 0 | return NULL; |
1053 | 0 | } |
1054 | 0 | } |
1055 | | |
1056 | | |
1057 | | u8 * tlsv1_server_send_alert(struct tlsv1_server *conn, u8 level, |
1058 | | u8 description, size_t *out_len) |
1059 | 0 | { |
1060 | 0 | u8 *alert, *pos, *length; |
1061 | |
|
1062 | 0 | tlsv1_server_log(conn, "Send Alert(%d:%d)", level, description); |
1063 | 0 | *out_len = 0; |
1064 | |
|
1065 | 0 | alert = os_malloc(10); |
1066 | 0 | if (alert == NULL) |
1067 | 0 | return NULL; |
1068 | | |
1069 | 0 | pos = alert; |
1070 | | |
1071 | | /* TLSPlaintext */ |
1072 | | /* ContentType type */ |
1073 | 0 | *pos++ = TLS_CONTENT_TYPE_ALERT; |
1074 | | /* ProtocolVersion version */ |
1075 | 0 | WPA_PUT_BE16(pos, conn->rl.tls_version ? conn->rl.tls_version : |
1076 | 0 | TLS_VERSION); |
1077 | 0 | pos += 2; |
1078 | | /* uint16 length (to be filled) */ |
1079 | 0 | length = pos; |
1080 | 0 | pos += 2; |
1081 | | /* opaque fragment[TLSPlaintext.length] */ |
1082 | | |
1083 | | /* Alert */ |
1084 | | /* AlertLevel level */ |
1085 | 0 | *pos++ = level; |
1086 | | /* AlertDescription description */ |
1087 | 0 | *pos++ = description; |
1088 | |
|
1089 | 0 | WPA_PUT_BE16(length, pos - length - 2); |
1090 | 0 | *out_len = pos - alert; |
1091 | |
|
1092 | 0 | return alert; |
1093 | 0 | } |