/src/hostap/src/tls/tlsv1_client_write.c
Line | Count | Source |
1 | | /* |
2 | | * TLSv1 client - write handshake message |
3 | | * Copyright (c) 2006-2015, 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_client.h" |
21 | | #include "tlsv1_client_i.h" |
22 | | |
23 | | |
24 | | static size_t tls_client_cert_chain_der_len(struct tlsv1_client *conn) |
25 | 0 | { |
26 | 0 | size_t len = 0; |
27 | 0 | struct x509_certificate *cert; |
28 | |
|
29 | 0 | if (conn->cred == NULL) |
30 | 0 | return 0; |
31 | | |
32 | 0 | cert = conn->cred->cert; |
33 | 0 | while (cert) { |
34 | 0 | len += 3 + cert->cert_len; |
35 | 0 | if (x509_certificate_self_signed(cert)) |
36 | 0 | break; |
37 | 0 | cert = x509_certificate_get_subject(conn->cred->trusted_certs, |
38 | 0 | &cert->issuer); |
39 | 0 | } |
40 | |
|
41 | 0 | return len; |
42 | 0 | } |
43 | | |
44 | | |
45 | | u8 * tls_send_client_hello(struct tlsv1_client *conn, size_t *out_len) |
46 | 0 | { |
47 | 0 | u8 *hello, *end, *pos, *hs_length, *hs_start, *rhdr; |
48 | 0 | struct os_time now; |
49 | 0 | size_t len, i; |
50 | 0 | u8 *ext_start; |
51 | 0 | u16 tls_version = tls_client_highest_ver(conn); |
52 | |
|
53 | 0 | if (!tls_version) { |
54 | 0 | wpa_printf(MSG_INFO, "TLSv1: No TLS version allowed"); |
55 | 0 | return NULL; |
56 | 0 | } |
57 | | |
58 | 0 | wpa_printf(MSG_DEBUG, "TLSv1: Send ClientHello (ver %s)", |
59 | 0 | tls_version_str(tls_version)); |
60 | 0 | *out_len = 0; |
61 | |
|
62 | 0 | os_get_time(&now); |
63 | 0 | #ifdef TEST_FUZZ |
64 | 0 | now.sec = 0xfffefdfc; |
65 | 0 | #endif /* TEST_FUZZ */ |
66 | 0 | WPA_PUT_BE32(conn->client_random, now.sec); |
67 | 0 | if (random_get_bytes(conn->client_random + 4, TLS_RANDOM_LEN - 4)) { |
68 | 0 | wpa_printf(MSG_ERROR, "TLSv1: Could not generate " |
69 | 0 | "client_random"); |
70 | 0 | return NULL; |
71 | 0 | } |
72 | 0 | wpa_hexdump(MSG_MSGDUMP, "TLSv1: client_random", |
73 | 0 | conn->client_random, TLS_RANDOM_LEN); |
74 | |
|
75 | 0 | len = 150 + conn->num_cipher_suites * 2 + conn->client_hello_ext_len; |
76 | 0 | hello = os_malloc(len); |
77 | 0 | if (hello == NULL) |
78 | 0 | return NULL; |
79 | 0 | end = hello + len; |
80 | |
|
81 | 0 | rhdr = hello; |
82 | 0 | pos = rhdr + TLS_RECORD_HEADER_LEN; |
83 | | |
84 | | /* opaque fragment[TLSPlaintext.length] */ |
85 | | |
86 | | /* Handshake */ |
87 | 0 | hs_start = pos; |
88 | | /* HandshakeType msg_type */ |
89 | 0 | *pos++ = TLS_HANDSHAKE_TYPE_CLIENT_HELLO; |
90 | | /* uint24 length (to be filled) */ |
91 | 0 | hs_length = pos; |
92 | 0 | pos += 3; |
93 | | /* body - ClientHello */ |
94 | | /* ProtocolVersion client_version */ |
95 | 0 | WPA_PUT_BE16(pos, tls_version); |
96 | 0 | pos += 2; |
97 | | /* Random random: uint32 gmt_unix_time, opaque random_bytes */ |
98 | 0 | os_memcpy(pos, conn->client_random, TLS_RANDOM_LEN); |
99 | 0 | pos += TLS_RANDOM_LEN; |
100 | | /* SessionID session_id */ |
101 | 0 | *pos++ = conn->session_id_len; |
102 | 0 | os_memcpy(pos, conn->session_id, conn->session_id_len); |
103 | 0 | pos += conn->session_id_len; |
104 | | /* CipherSuite cipher_suites<2..2^16-1> */ |
105 | 0 | WPA_PUT_BE16(pos, 2 * conn->num_cipher_suites); |
106 | 0 | pos += 2; |
107 | 0 | for (i = 0; i < conn->num_cipher_suites; i++) { |
108 | 0 | WPA_PUT_BE16(pos, conn->cipher_suites[i]); |
109 | 0 | pos += 2; |
110 | 0 | } |
111 | | /* CompressionMethod compression_methods<1..2^8-1> */ |
112 | 0 | *pos++ = 1; |
113 | 0 | *pos++ = TLS_COMPRESSION_NULL; |
114 | | |
115 | | /* Extension */ |
116 | 0 | ext_start = pos; |
117 | 0 | pos += 2; |
118 | |
|
119 | 0 | #ifdef CONFIG_TLSV12 |
120 | 0 | if (conn->rl.tls_version >= TLS_VERSION_1_2) { |
121 | | /* |
122 | | * Add signature_algorithms extension since we support only |
123 | | * SHA256 (and not the default SHA1) with TLSv1.2. |
124 | | */ |
125 | | /* ExtensionsType extension_type = signature_algorithms(13) */ |
126 | 0 | WPA_PUT_BE16(pos, TLS_EXT_SIGNATURE_ALGORITHMS); |
127 | 0 | pos += 2; |
128 | | /* opaque extension_data<0..2^16-1> length */ |
129 | 0 | WPA_PUT_BE16(pos, 8); |
130 | 0 | pos += 2; |
131 | | /* supported_signature_algorithms<2..2^16-2> length */ |
132 | 0 | WPA_PUT_BE16(pos, 6); |
133 | 0 | pos += 2; |
134 | | /* supported_signature_algorithms */ |
135 | 0 | *pos++ = TLS_HASH_ALG_SHA512; |
136 | 0 | *pos++ = TLS_SIGN_ALG_RSA; |
137 | 0 | *pos++ = TLS_HASH_ALG_SHA384; |
138 | 0 | *pos++ = TLS_SIGN_ALG_RSA; |
139 | 0 | *pos++ = TLS_HASH_ALG_SHA256; |
140 | 0 | *pos++ = TLS_SIGN_ALG_RSA; |
141 | 0 | } |
142 | 0 | #endif /* CONFIG_TLSV12 */ |
143 | |
|
144 | 0 | if (conn->client_hello_ext) { |
145 | 0 | os_memcpy(pos, conn->client_hello_ext, |
146 | 0 | conn->client_hello_ext_len); |
147 | 0 | pos += conn->client_hello_ext_len; |
148 | 0 | } |
149 | |
|
150 | 0 | if (conn->flags & TLS_CONN_REQUEST_OCSP) { |
151 | 0 | wpa_printf(MSG_DEBUG, |
152 | 0 | "TLSv1: Add status_request extension for OCSP stapling"); |
153 | | /* ExtensionsType extension_type = status_request(5) */ |
154 | 0 | WPA_PUT_BE16(pos, TLS_EXT_STATUS_REQUEST); |
155 | 0 | pos += 2; |
156 | | /* opaque extension_data<0..2^16-1> length */ |
157 | 0 | WPA_PUT_BE16(pos, 5); |
158 | 0 | pos += 2; |
159 | | |
160 | | /* |
161 | | * RFC 6066, 8: |
162 | | * struct { |
163 | | * CertificateStatusType status_type; |
164 | | * select (status_type) { |
165 | | * case ocsp: OCSPStatusRequest; |
166 | | * } request; |
167 | | * } CertificateStatusRequest; |
168 | | * |
169 | | * enum { ocsp(1), (255) } CertificateStatusType; |
170 | | */ |
171 | 0 | *pos++ = 1; /* status_type = ocsp(1) */ |
172 | | |
173 | | /* |
174 | | * struct { |
175 | | * ResponderID responder_id_list<0..2^16-1>; |
176 | | * Extensions request_extensions; |
177 | | * } OCSPStatusRequest; |
178 | | * |
179 | | * opaque ResponderID<1..2^16-1>; |
180 | | * opaque Extensions<0..2^16-1>; |
181 | | */ |
182 | 0 | WPA_PUT_BE16(pos, 0); /* responder_id_list(empty) */ |
183 | 0 | pos += 2; |
184 | 0 | WPA_PUT_BE16(pos, 0); /* request_extensions(empty) */ |
185 | 0 | pos += 2; |
186 | |
|
187 | 0 | wpa_printf(MSG_DEBUG, |
188 | 0 | "TLSv1: Add status_request_v2 extension for OCSP stapling"); |
189 | | /* ExtensionsType extension_type = status_request_v2(17) */ |
190 | 0 | WPA_PUT_BE16(pos, TLS_EXT_STATUS_REQUEST_V2); |
191 | 0 | pos += 2; |
192 | | /* opaque extension_data<0..2^16-1> length */ |
193 | 0 | WPA_PUT_BE16(pos, 7); |
194 | 0 | pos += 2; |
195 | | |
196 | | /* |
197 | | * RFC 6961, 2.2: |
198 | | * struct { |
199 | | * CertificateStatusType status_type; |
200 | | * uint16 request_length; |
201 | | * select (status_type) { |
202 | | * case ocsp: OCSPStatusRequest; |
203 | | * case ocsp_multi: OCSPStatusRequest; |
204 | | * } request; |
205 | | * } CertificateStatusRequestItemV2; |
206 | | * |
207 | | * enum { ocsp(1), ocsp_multi(2), (255) } CertificateStatusType; |
208 | | * |
209 | | * struct { |
210 | | * CertificateStatusRequestItemV2 |
211 | | * certificate_status_req_list<1..2^16-1>; |
212 | | * } CertificateStatusRequestListV2; |
213 | | */ |
214 | | |
215 | | /* certificate_status_req_list<1..2^16-1> */ |
216 | 0 | WPA_PUT_BE16(pos, 5); |
217 | 0 | pos += 2; |
218 | | |
219 | | /* CertificateStatusRequestItemV2 */ |
220 | 0 | *pos++ = 2; /* status_type = ocsp_multi(2) */ |
221 | | /* OCSPStatusRequest as shown above for v1 */ |
222 | 0 | WPA_PUT_BE16(pos, 0); /* responder_id_list(empty) */ |
223 | 0 | pos += 2; |
224 | 0 | WPA_PUT_BE16(pos, 0); /* request_extensions(empty) */ |
225 | 0 | pos += 2; |
226 | 0 | } |
227 | |
|
228 | 0 | if (pos == ext_start + 2) |
229 | 0 | pos -= 2; /* no extensions */ |
230 | 0 | else |
231 | 0 | WPA_PUT_BE16(ext_start, pos - ext_start - 2); |
232 | |
|
233 | 0 | WPA_PUT_BE24(hs_length, pos - hs_length - 3); |
234 | 0 | tls_verify_hash_add(&conn->verify, hs_start, pos - hs_start); |
235 | |
|
236 | 0 | if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_HANDSHAKE, |
237 | 0 | rhdr, end - rhdr, hs_start, pos - hs_start, |
238 | 0 | out_len) < 0) { |
239 | 0 | wpa_printf(MSG_DEBUG, "TLSv1: Failed to create TLS record"); |
240 | 0 | tls_alert(conn, TLS_ALERT_LEVEL_FATAL, |
241 | 0 | TLS_ALERT_INTERNAL_ERROR); |
242 | 0 | os_free(hello); |
243 | 0 | return NULL; |
244 | 0 | } |
245 | | |
246 | 0 | conn->state = SERVER_HELLO; |
247 | |
|
248 | 0 | return hello; |
249 | 0 | } |
250 | | |
251 | | |
252 | | static int tls_write_client_certificate(struct tlsv1_client *conn, |
253 | | u8 **msgpos, u8 *end) |
254 | 0 | { |
255 | 0 | u8 *pos, *rhdr, *hs_start, *hs_length, *cert_start; |
256 | 0 | size_t rlen; |
257 | 0 | struct x509_certificate *cert; |
258 | |
|
259 | 0 | pos = *msgpos; |
260 | 0 | if (TLS_RECORD_HEADER_LEN + 1 + 3 + 3 > end - pos) { |
261 | 0 | tls_alert(conn, TLS_ALERT_LEVEL_FATAL, |
262 | 0 | TLS_ALERT_INTERNAL_ERROR); |
263 | 0 | return -1; |
264 | 0 | } |
265 | | |
266 | 0 | wpa_printf(MSG_DEBUG, "TLSv1: Send Certificate"); |
267 | 0 | rhdr = pos; |
268 | 0 | pos += TLS_RECORD_HEADER_LEN; |
269 | | |
270 | | /* opaque fragment[TLSPlaintext.length] */ |
271 | | |
272 | | /* Handshake */ |
273 | 0 | hs_start = pos; |
274 | | /* HandshakeType msg_type */ |
275 | 0 | *pos++ = TLS_HANDSHAKE_TYPE_CERTIFICATE; |
276 | | /* uint24 length (to be filled) */ |
277 | 0 | hs_length = pos; |
278 | 0 | pos += 3; |
279 | | /* body - Certificate */ |
280 | | /* uint24 length (to be filled) */ |
281 | 0 | cert_start = pos; |
282 | 0 | pos += 3; |
283 | 0 | cert = conn->cred ? conn->cred->cert : NULL; |
284 | 0 | while (cert) { |
285 | 0 | if (3 + cert->cert_len > (size_t) (end - pos)) { |
286 | 0 | wpa_printf(MSG_DEBUG, "TLSv1: Not enough buffer space " |
287 | 0 | "for Certificate (cert_len=%lu left=%lu)", |
288 | 0 | (unsigned long) cert->cert_len, |
289 | 0 | (unsigned long) (end - pos)); |
290 | 0 | tls_alert(conn, TLS_ALERT_LEVEL_FATAL, |
291 | 0 | TLS_ALERT_INTERNAL_ERROR); |
292 | 0 | return -1; |
293 | 0 | } |
294 | 0 | WPA_PUT_BE24(pos, cert->cert_len); |
295 | 0 | pos += 3; |
296 | 0 | os_memcpy(pos, cert->cert_start, cert->cert_len); |
297 | 0 | pos += cert->cert_len; |
298 | |
|
299 | 0 | if (x509_certificate_self_signed(cert)) |
300 | 0 | break; |
301 | 0 | cert = x509_certificate_get_subject(conn->cred->trusted_certs, |
302 | 0 | &cert->issuer); |
303 | 0 | } |
304 | 0 | if (conn->cred == NULL || cert == conn->cred->cert || cert == NULL) { |
305 | | /* |
306 | | * Client was not configured with all the needed certificates |
307 | | * to form a full certificate chain. The server may fail to |
308 | | * validate the chain unless it is configured with all the |
309 | | * missing CA certificates. |
310 | | */ |
311 | 0 | wpa_printf(MSG_DEBUG, "TLSv1: Full client certificate chain " |
312 | 0 | "not configured - validation may fail"); |
313 | 0 | } |
314 | 0 | WPA_PUT_BE24(cert_start, pos - cert_start - 3); |
315 | |
|
316 | 0 | WPA_PUT_BE24(hs_length, pos - hs_length - 3); |
317 | |
|
318 | 0 | if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_HANDSHAKE, |
319 | 0 | rhdr, end - rhdr, hs_start, pos - hs_start, |
320 | 0 | &rlen) < 0) { |
321 | 0 | wpa_printf(MSG_DEBUG, "TLSv1: Failed to generate a record"); |
322 | 0 | tls_alert(conn, TLS_ALERT_LEVEL_FATAL, |
323 | 0 | TLS_ALERT_INTERNAL_ERROR); |
324 | 0 | return -1; |
325 | 0 | } |
326 | 0 | pos = rhdr + rlen; |
327 | |
|
328 | 0 | tls_verify_hash_add(&conn->verify, hs_start, pos - hs_start); |
329 | |
|
330 | 0 | *msgpos = pos; |
331 | |
|
332 | 0 | return 0; |
333 | 0 | } |
334 | | |
335 | | |
336 | | static int tlsv1_key_x_dh(struct tlsv1_client *conn, u8 **pos, u8 *end) |
337 | 0 | { |
338 | | /* ClientDiffieHellmanPublic */ |
339 | 0 | u8 *csecret, *csecret_start, *dh_yc, *shared; |
340 | 0 | size_t csecret_len, dh_yc_len, shared_len; |
341 | |
|
342 | 0 | csecret_len = conn->dh_p_len; |
343 | 0 | csecret = os_malloc(csecret_len); |
344 | 0 | if (csecret == NULL) { |
345 | 0 | wpa_printf(MSG_DEBUG, "TLSv1: Failed to allocate " |
346 | 0 | "memory for Yc (Diffie-Hellman)"); |
347 | 0 | tls_alert(conn, TLS_ALERT_LEVEL_FATAL, |
348 | 0 | TLS_ALERT_INTERNAL_ERROR); |
349 | 0 | return -1; |
350 | 0 | } |
351 | 0 | if (random_get_bytes(csecret, csecret_len)) { |
352 | 0 | wpa_printf(MSG_DEBUG, "TLSv1: Failed to get random " |
353 | 0 | "data for Diffie-Hellman"); |
354 | 0 | tls_alert(conn, TLS_ALERT_LEVEL_FATAL, |
355 | 0 | TLS_ALERT_INTERNAL_ERROR); |
356 | 0 | os_free(csecret); |
357 | 0 | return -1; |
358 | 0 | } |
359 | | |
360 | 0 | if (os_memcmp(csecret, conn->dh_p, csecret_len) > 0) |
361 | 0 | csecret[0] = 0; /* make sure Yc < p */ |
362 | |
|
363 | 0 | csecret_start = csecret; |
364 | 0 | while (csecret_len > 1 && *csecret_start == 0) { |
365 | 0 | csecret_start++; |
366 | 0 | csecret_len--; |
367 | 0 | } |
368 | 0 | wpa_hexdump_key(MSG_DEBUG, "TLSv1: DH client's secret value", |
369 | 0 | csecret_start, csecret_len); |
370 | | |
371 | | /* Yc = g^csecret mod p */ |
372 | 0 | dh_yc_len = conn->dh_p_len; |
373 | 0 | dh_yc = os_malloc(dh_yc_len); |
374 | 0 | if (dh_yc == NULL) { |
375 | 0 | wpa_printf(MSG_DEBUG, "TLSv1: Failed to allocate " |
376 | 0 | "memory for Diffie-Hellman"); |
377 | 0 | tls_alert(conn, TLS_ALERT_LEVEL_FATAL, |
378 | 0 | TLS_ALERT_INTERNAL_ERROR); |
379 | 0 | os_free(csecret); |
380 | 0 | return -1; |
381 | 0 | } |
382 | 0 | if (crypto_mod_exp(conn->dh_g, conn->dh_g_len, |
383 | 0 | csecret_start, csecret_len, |
384 | 0 | conn->dh_p, conn->dh_p_len, |
385 | 0 | dh_yc, &dh_yc_len)) { |
386 | 0 | tls_alert(conn, TLS_ALERT_LEVEL_FATAL, |
387 | 0 | TLS_ALERT_INTERNAL_ERROR); |
388 | 0 | os_free(csecret); |
389 | 0 | os_free(dh_yc); |
390 | 0 | return -1; |
391 | 0 | } |
392 | | |
393 | 0 | wpa_hexdump(MSG_DEBUG, "TLSv1: DH Yc (client's public value)", |
394 | 0 | dh_yc, dh_yc_len); |
395 | |
|
396 | 0 | if (end - *pos < 2) { |
397 | 0 | tls_alert(conn, TLS_ALERT_LEVEL_FATAL, |
398 | 0 | TLS_ALERT_INTERNAL_ERROR); |
399 | 0 | os_free(csecret); |
400 | 0 | os_free(dh_yc); |
401 | 0 | return -1; |
402 | 0 | } |
403 | 0 | WPA_PUT_BE16(*pos, dh_yc_len); |
404 | 0 | *pos += 2; |
405 | 0 | if (dh_yc_len > (size_t) (end - *pos)) { |
406 | 0 | wpa_printf(MSG_DEBUG, "TLSv1: Not enough room in the " |
407 | 0 | "message buffer for Yc"); |
408 | 0 | tls_alert(conn, TLS_ALERT_LEVEL_FATAL, |
409 | 0 | TLS_ALERT_INTERNAL_ERROR); |
410 | 0 | os_free(csecret); |
411 | 0 | os_free(dh_yc); |
412 | 0 | return -1; |
413 | 0 | } |
414 | 0 | os_memcpy(*pos, dh_yc, dh_yc_len); |
415 | 0 | *pos += dh_yc_len; |
416 | 0 | os_free(dh_yc); |
417 | |
|
418 | 0 | shared_len = conn->dh_p_len; |
419 | 0 | shared = os_malloc(shared_len); |
420 | 0 | if (shared == NULL) { |
421 | 0 | wpa_printf(MSG_DEBUG, "TLSv1: Could not allocate memory for " |
422 | 0 | "DH"); |
423 | 0 | tls_alert(conn, TLS_ALERT_LEVEL_FATAL, |
424 | 0 | TLS_ALERT_INTERNAL_ERROR); |
425 | 0 | os_free(csecret); |
426 | 0 | return -1; |
427 | 0 | } |
428 | | |
429 | | /* shared = Ys^csecret mod p */ |
430 | 0 | if (crypto_mod_exp(conn->dh_ys, conn->dh_ys_len, |
431 | 0 | csecret_start, csecret_len, |
432 | 0 | conn->dh_p, conn->dh_p_len, |
433 | 0 | shared, &shared_len)) { |
434 | 0 | tls_alert(conn, TLS_ALERT_LEVEL_FATAL, |
435 | 0 | TLS_ALERT_INTERNAL_ERROR); |
436 | 0 | os_free(csecret); |
437 | 0 | os_free(shared); |
438 | 0 | return -1; |
439 | 0 | } |
440 | 0 | wpa_hexdump_key(MSG_DEBUG, "TLSv1: Shared secret from DH key exchange", |
441 | 0 | shared, shared_len); |
442 | |
|
443 | 0 | os_memset(csecret_start, 0, csecret_len); |
444 | 0 | os_free(csecret); |
445 | 0 | if (tls_derive_keys(conn, shared, shared_len)) { |
446 | 0 | wpa_printf(MSG_DEBUG, "TLSv1: Failed to derive keys"); |
447 | 0 | tls_alert(conn, TLS_ALERT_LEVEL_FATAL, |
448 | 0 | TLS_ALERT_INTERNAL_ERROR); |
449 | 0 | os_free(shared); |
450 | 0 | return -1; |
451 | 0 | } |
452 | 0 | os_memset(shared, 0, shared_len); |
453 | 0 | os_free(shared); |
454 | 0 | tlsv1_client_free_dh(conn); |
455 | 0 | return 0; |
456 | 0 | } |
457 | | |
458 | | |
459 | | static int tlsv1_key_x_rsa(struct tlsv1_client *conn, u8 **pos, u8 *end) |
460 | 0 | { |
461 | 0 | u8 pre_master_secret[TLS_PRE_MASTER_SECRET_LEN]; |
462 | 0 | size_t clen; |
463 | 0 | int res; |
464 | |
|
465 | 0 | if (tls_derive_pre_master_secret(conn, pre_master_secret) < 0 || |
466 | 0 | tls_derive_keys(conn, pre_master_secret, |
467 | 0 | TLS_PRE_MASTER_SECRET_LEN)) { |
468 | 0 | wpa_printf(MSG_DEBUG, "TLSv1: Failed to derive keys"); |
469 | 0 | tls_alert(conn, TLS_ALERT_LEVEL_FATAL, |
470 | 0 | TLS_ALERT_INTERNAL_ERROR); |
471 | 0 | return -1; |
472 | 0 | } |
473 | | |
474 | | /* EncryptedPreMasterSecret */ |
475 | 0 | if (conn->server_rsa_key == NULL) { |
476 | 0 | wpa_printf(MSG_DEBUG, "TLSv1: No server RSA key to " |
477 | 0 | "use for encrypting pre-master secret"); |
478 | 0 | tls_alert(conn, TLS_ALERT_LEVEL_FATAL, |
479 | 0 | TLS_ALERT_INTERNAL_ERROR); |
480 | 0 | return -1; |
481 | 0 | } |
482 | | |
483 | | /* RSA encrypted value is encoded with PKCS #1 v1.5 block type 2. */ |
484 | 0 | *pos += 2; |
485 | 0 | clen = end - *pos; |
486 | 0 | res = crypto_public_key_encrypt_pkcs1_v15( |
487 | 0 | conn->server_rsa_key, |
488 | 0 | pre_master_secret, TLS_PRE_MASTER_SECRET_LEN, |
489 | 0 | *pos, &clen); |
490 | 0 | os_memset(pre_master_secret, 0, TLS_PRE_MASTER_SECRET_LEN); |
491 | 0 | if (res < 0) { |
492 | 0 | wpa_printf(MSG_DEBUG, "TLSv1: RSA encryption failed"); |
493 | 0 | tls_alert(conn, TLS_ALERT_LEVEL_FATAL, |
494 | 0 | TLS_ALERT_INTERNAL_ERROR); |
495 | 0 | return -1; |
496 | 0 | } |
497 | 0 | WPA_PUT_BE16(*pos - 2, clen); |
498 | 0 | wpa_hexdump(MSG_MSGDUMP, "TLSv1: Encrypted pre_master_secret", |
499 | 0 | *pos, clen); |
500 | 0 | *pos += clen; |
501 | |
|
502 | 0 | return 0; |
503 | 0 | } |
504 | | |
505 | | |
506 | | static int tls_write_client_key_exchange(struct tlsv1_client *conn, |
507 | | u8 **msgpos, u8 *end) |
508 | 0 | { |
509 | 0 | u8 *pos, *rhdr, *hs_start, *hs_length; |
510 | 0 | size_t rlen; |
511 | 0 | tls_key_exchange keyx; |
512 | 0 | const struct tls_cipher_suite *suite; |
513 | |
|
514 | 0 | suite = tls_get_cipher_suite(conn->rl.cipher_suite); |
515 | 0 | if (suite == NULL) |
516 | 0 | keyx = TLS_KEY_X_NULL; |
517 | 0 | else |
518 | 0 | keyx = suite->key_exchange; |
519 | |
|
520 | 0 | pos = *msgpos; |
521 | |
|
522 | 0 | wpa_printf(MSG_DEBUG, "TLSv1: Send ClientKeyExchange"); |
523 | |
|
524 | 0 | rhdr = pos; |
525 | 0 | pos += TLS_RECORD_HEADER_LEN; |
526 | | |
527 | | /* opaque fragment[TLSPlaintext.length] */ |
528 | | |
529 | | /* Handshake */ |
530 | 0 | hs_start = pos; |
531 | | /* HandshakeType msg_type */ |
532 | 0 | *pos++ = TLS_HANDSHAKE_TYPE_CLIENT_KEY_EXCHANGE; |
533 | | /* uint24 length (to be filled) */ |
534 | 0 | hs_length = pos; |
535 | 0 | pos += 3; |
536 | | /* body - ClientKeyExchange */ |
537 | 0 | if (keyx == TLS_KEY_X_DH_anon || keyx == TLS_KEY_X_DHE_RSA) { |
538 | 0 | if (tlsv1_key_x_dh(conn, &pos, end) < 0) |
539 | 0 | return -1; |
540 | 0 | } else { |
541 | 0 | if (tlsv1_key_x_rsa(conn, &pos, end) < 0) |
542 | 0 | return -1; |
543 | 0 | } |
544 | | |
545 | 0 | WPA_PUT_BE24(hs_length, pos - hs_length - 3); |
546 | |
|
547 | 0 | if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_HANDSHAKE, |
548 | 0 | rhdr, end - rhdr, hs_start, pos - hs_start, |
549 | 0 | &rlen) < 0) { |
550 | 0 | wpa_printf(MSG_DEBUG, "TLSv1: Failed to create a record"); |
551 | 0 | tls_alert(conn, TLS_ALERT_LEVEL_FATAL, |
552 | 0 | TLS_ALERT_INTERNAL_ERROR); |
553 | 0 | return -1; |
554 | 0 | } |
555 | 0 | pos = rhdr + rlen; |
556 | 0 | tls_verify_hash_add(&conn->verify, hs_start, pos - hs_start); |
557 | |
|
558 | 0 | *msgpos = pos; |
559 | |
|
560 | 0 | return 0; |
561 | 0 | } |
562 | | |
563 | | |
564 | | static int tls_write_client_certificate_verify(struct tlsv1_client *conn, |
565 | | u8 **msgpos, u8 *end) |
566 | 0 | { |
567 | 0 | u8 *pos, *rhdr, *hs_start, *hs_length, *signed_start; |
568 | 0 | size_t rlen, hlen, clen; |
569 | 0 | u8 hash[100], *hpos; |
570 | |
|
571 | 0 | pos = *msgpos; |
572 | |
|
573 | 0 | wpa_printf(MSG_DEBUG, "TLSv1: Send CertificateVerify"); |
574 | 0 | rhdr = pos; |
575 | 0 | pos += TLS_RECORD_HEADER_LEN; |
576 | | |
577 | | /* Handshake */ |
578 | 0 | hs_start = pos; |
579 | | /* HandshakeType msg_type */ |
580 | 0 | *pos++ = TLS_HANDSHAKE_TYPE_CERTIFICATE_VERIFY; |
581 | | /* uint24 length (to be filled) */ |
582 | 0 | hs_length = pos; |
583 | 0 | pos += 3; |
584 | | |
585 | | /* |
586 | | * RFC 2246: 7.4.3 and 7.4.8: |
587 | | * Signature signature |
588 | | * |
589 | | * RSA: |
590 | | * digitally-signed struct { |
591 | | * opaque md5_hash[16]; |
592 | | * opaque sha_hash[20]; |
593 | | * }; |
594 | | * |
595 | | * DSA: |
596 | | * digitally-signed struct { |
597 | | * opaque sha_hash[20]; |
598 | | * }; |
599 | | * |
600 | | * The hash values are calculated over all handshake messages sent or |
601 | | * received starting at ClientHello up to, but not including, this |
602 | | * CertificateVerify message, including the type and length fields of |
603 | | * the handshake messages. |
604 | | */ |
605 | |
|
606 | 0 | hpos = hash; |
607 | |
|
608 | 0 | #ifdef CONFIG_TLSV12 |
609 | 0 | if (conn->rl.tls_version == TLS_VERSION_1_2) { |
610 | 0 | hlen = SHA256_MAC_LEN; |
611 | 0 | if (conn->verify.sha256_cert == NULL || |
612 | 0 | crypto_hash_finish(conn->verify.sha256_cert, hpos, &hlen) < |
613 | 0 | 0) { |
614 | 0 | conn->verify.sha256_cert = NULL; |
615 | 0 | tls_alert(conn, TLS_ALERT_LEVEL_FATAL, |
616 | 0 | TLS_ALERT_INTERNAL_ERROR); |
617 | 0 | return -1; |
618 | 0 | } |
619 | 0 | conn->verify.sha256_cert = NULL; |
620 | | |
621 | | /* |
622 | | * RFC 3447, A.2.4 RSASSA-PKCS1-v1_5 |
623 | | * |
624 | | * DigestInfo ::= SEQUENCE { |
625 | | * digestAlgorithm DigestAlgorithm, |
626 | | * digest OCTET STRING |
627 | | * } |
628 | | * |
629 | | * SHA-256 OID: sha256WithRSAEncryption ::= {pkcs-1 11} |
630 | | * |
631 | | * DER encoded DigestInfo for SHA256 per RFC 3447: |
632 | | * 30 31 30 0d 06 09 60 86 48 01 65 03 04 02 01 05 00 04 20 || |
633 | | * H |
634 | | */ |
635 | 0 | os_memmove(hash + 19, hash, hlen); |
636 | 0 | hlen += 19; |
637 | 0 | os_memcpy(hash, "\x30\x31\x30\x0d\x06\x09\x60\x86\x48\x01\x65" |
638 | 0 | "\x03\x04\x02\x01\x05\x00\x04\x20", 19); |
639 | 0 | } else { |
640 | 0 | #endif /* CONFIG_TLSV12 */ |
641 | |
|
642 | 0 | hlen = MD5_MAC_LEN; |
643 | 0 | if (conn->verify.md5_cert == NULL || |
644 | 0 | crypto_hash_finish(conn->verify.md5_cert, hpos, &hlen) < 0) { |
645 | 0 | tls_alert(conn, TLS_ALERT_LEVEL_FATAL, |
646 | 0 | TLS_ALERT_INTERNAL_ERROR); |
647 | 0 | conn->verify.md5_cert = NULL; |
648 | 0 | crypto_hash_finish(conn->verify.sha1_cert, NULL, NULL); |
649 | 0 | conn->verify.sha1_cert = NULL; |
650 | 0 | return -1; |
651 | 0 | } |
652 | 0 | hpos += MD5_MAC_LEN; |
653 | |
|
654 | 0 | conn->verify.md5_cert = NULL; |
655 | 0 | hlen = SHA1_MAC_LEN; |
656 | 0 | if (conn->verify.sha1_cert == NULL || |
657 | 0 | crypto_hash_finish(conn->verify.sha1_cert, hpos, &hlen) < 0) { |
658 | 0 | conn->verify.sha1_cert = NULL; |
659 | 0 | tls_alert(conn, TLS_ALERT_LEVEL_FATAL, |
660 | 0 | TLS_ALERT_INTERNAL_ERROR); |
661 | 0 | return -1; |
662 | 0 | } |
663 | 0 | conn->verify.sha1_cert = NULL; |
664 | |
|
665 | 0 | hlen += MD5_MAC_LEN; |
666 | |
|
667 | 0 | #ifdef CONFIG_TLSV12 |
668 | 0 | } |
669 | 0 | #endif /* CONFIG_TLSV12 */ |
670 | | |
671 | 0 | wpa_hexdump(MSG_MSGDUMP, "TLSv1: CertificateVerify hash", hash, hlen); |
672 | |
|
673 | 0 | #ifdef CONFIG_TLSV12 |
674 | 0 | if (conn->rl.tls_version >= TLS_VERSION_1_2) { |
675 | | /* |
676 | | * RFC 5246, 4.7: |
677 | | * TLS v1.2 adds explicit indication of the used signature and |
678 | | * hash algorithms. |
679 | | * |
680 | | * struct { |
681 | | * HashAlgorithm hash; |
682 | | * SignatureAlgorithm signature; |
683 | | * } SignatureAndHashAlgorithm; |
684 | | */ |
685 | 0 | *pos++ = TLS_HASH_ALG_SHA256; |
686 | 0 | *pos++ = TLS_SIGN_ALG_RSA; |
687 | 0 | } |
688 | 0 | #endif /* CONFIG_TLSV12 */ |
689 | | |
690 | | /* |
691 | | * RFC 2246, 4.7: |
692 | | * In digital signing, one-way hash functions are used as input for a |
693 | | * signing algorithm. A digitally-signed element is encoded as an |
694 | | * opaque vector <0..2^16-1>, where the length is specified by the |
695 | | * signing algorithm and key. |
696 | | * |
697 | | * In RSA signing, a 36-byte structure of two hashes (one SHA and one |
698 | | * MD5) is signed (encrypted with the private key). It is encoded with |
699 | | * PKCS #1 block type 0 or type 1 as described in [PKCS1]. |
700 | | */ |
701 | 0 | signed_start = pos; /* length to be filled */ |
702 | 0 | pos += 2; |
703 | 0 | clen = end - pos; |
704 | 0 | if (conn->cred == NULL || |
705 | 0 | crypto_private_key_sign_pkcs1(conn->cred->key, hash, hlen, |
706 | 0 | pos, &clen) < 0) { |
707 | 0 | wpa_printf(MSG_DEBUG, "TLSv1: Failed to sign hash (PKCS #1)"); |
708 | 0 | tls_alert(conn, TLS_ALERT_LEVEL_FATAL, |
709 | 0 | TLS_ALERT_INTERNAL_ERROR); |
710 | 0 | return -1; |
711 | 0 | } |
712 | 0 | WPA_PUT_BE16(signed_start, clen); |
713 | |
|
714 | 0 | pos += clen; |
715 | |
|
716 | 0 | WPA_PUT_BE24(hs_length, pos - hs_length - 3); |
717 | |
|
718 | 0 | if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_HANDSHAKE, |
719 | 0 | rhdr, end - rhdr, hs_start, pos - hs_start, |
720 | 0 | &rlen) < 0) { |
721 | 0 | wpa_printf(MSG_DEBUG, "TLSv1: Failed to generate a record"); |
722 | 0 | tls_alert(conn, TLS_ALERT_LEVEL_FATAL, |
723 | 0 | TLS_ALERT_INTERNAL_ERROR); |
724 | 0 | return -1; |
725 | 0 | } |
726 | 0 | pos = rhdr + rlen; |
727 | |
|
728 | 0 | tls_verify_hash_add(&conn->verify, hs_start, pos - hs_start); |
729 | |
|
730 | 0 | *msgpos = pos; |
731 | |
|
732 | 0 | return 0; |
733 | 0 | } |
734 | | |
735 | | |
736 | | static int tls_write_client_change_cipher_spec(struct tlsv1_client *conn, |
737 | | u8 **msgpos, u8 *end) |
738 | 0 | { |
739 | 0 | size_t rlen; |
740 | 0 | u8 payload[1]; |
741 | |
|
742 | 0 | wpa_printf(MSG_DEBUG, "TLSv1: Send ChangeCipherSpec"); |
743 | |
|
744 | 0 | payload[0] = TLS_CHANGE_CIPHER_SPEC; |
745 | |
|
746 | 0 | if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_CHANGE_CIPHER_SPEC, |
747 | 0 | *msgpos, end - *msgpos, payload, sizeof(payload), |
748 | 0 | &rlen) < 0) { |
749 | 0 | wpa_printf(MSG_DEBUG, "TLSv1: Failed to create a record"); |
750 | 0 | tls_alert(conn, TLS_ALERT_LEVEL_FATAL, |
751 | 0 | TLS_ALERT_INTERNAL_ERROR); |
752 | 0 | return -1; |
753 | 0 | } |
754 | | |
755 | 0 | if (tlsv1_record_change_write_cipher(&conn->rl) < 0) { |
756 | 0 | wpa_printf(MSG_DEBUG, "TLSv1: Failed to set write cipher for " |
757 | 0 | "record layer"); |
758 | 0 | tls_alert(conn, TLS_ALERT_LEVEL_FATAL, |
759 | 0 | TLS_ALERT_INTERNAL_ERROR); |
760 | 0 | return -1; |
761 | 0 | } |
762 | | |
763 | 0 | *msgpos += rlen; |
764 | |
|
765 | 0 | return 0; |
766 | 0 | } |
767 | | |
768 | | |
769 | | static int tls_write_client_finished(struct tlsv1_client *conn, |
770 | | u8 **msgpos, u8 *end) |
771 | 0 | { |
772 | 0 | u8 *pos, *hs_start; |
773 | 0 | size_t rlen, hlen; |
774 | 0 | u8 verify_data[1 + 3 + TLS_VERIFY_DATA_LEN]; |
775 | 0 | u8 hash[MD5_MAC_LEN + SHA1_MAC_LEN]; |
776 | |
|
777 | 0 | wpa_printf(MSG_DEBUG, "TLSv1: Send Finished"); |
778 | | |
779 | | /* Encrypted Handshake Message: Finished */ |
780 | |
|
781 | 0 | #ifdef CONFIG_TLSV12 |
782 | 0 | if (conn->rl.tls_version >= TLS_VERSION_1_2) { |
783 | 0 | hlen = SHA256_MAC_LEN; |
784 | 0 | if (conn->verify.sha256_client == NULL || |
785 | 0 | crypto_hash_finish(conn->verify.sha256_client, hash, &hlen) |
786 | 0 | < 0) { |
787 | 0 | tls_alert(conn, TLS_ALERT_LEVEL_FATAL, |
788 | 0 | TLS_ALERT_INTERNAL_ERROR); |
789 | 0 | conn->verify.sha256_client = NULL; |
790 | 0 | return -1; |
791 | 0 | } |
792 | 0 | conn->verify.sha256_client = NULL; |
793 | 0 | } else { |
794 | 0 | #endif /* CONFIG_TLSV12 */ |
795 | |
|
796 | 0 | hlen = MD5_MAC_LEN; |
797 | 0 | if (conn->verify.md5_client == NULL || |
798 | 0 | crypto_hash_finish(conn->verify.md5_client, hash, &hlen) < 0) { |
799 | 0 | tls_alert(conn, TLS_ALERT_LEVEL_FATAL, |
800 | 0 | TLS_ALERT_INTERNAL_ERROR); |
801 | 0 | conn->verify.md5_client = NULL; |
802 | 0 | crypto_hash_finish(conn->verify.sha1_client, NULL, NULL); |
803 | 0 | conn->verify.sha1_client = NULL; |
804 | 0 | return -1; |
805 | 0 | } |
806 | 0 | conn->verify.md5_client = NULL; |
807 | 0 | hlen = SHA1_MAC_LEN; |
808 | 0 | if (conn->verify.sha1_client == NULL || |
809 | 0 | crypto_hash_finish(conn->verify.sha1_client, hash + MD5_MAC_LEN, |
810 | 0 | &hlen) < 0) { |
811 | 0 | conn->verify.sha1_client = NULL; |
812 | 0 | tls_alert(conn, TLS_ALERT_LEVEL_FATAL, |
813 | 0 | TLS_ALERT_INTERNAL_ERROR); |
814 | 0 | return -1; |
815 | 0 | } |
816 | 0 | conn->verify.sha1_client = NULL; |
817 | 0 | hlen = MD5_MAC_LEN + SHA1_MAC_LEN; |
818 | |
|
819 | 0 | #ifdef CONFIG_TLSV12 |
820 | 0 | } |
821 | 0 | #endif /* CONFIG_TLSV12 */ |
822 | | |
823 | 0 | if (tls_prf(conn->rl.tls_version, |
824 | 0 | conn->master_secret, TLS_MASTER_SECRET_LEN, |
825 | 0 | "client finished", hash, hlen, |
826 | 0 | verify_data + 1 + 3, TLS_VERIFY_DATA_LEN)) { |
827 | 0 | wpa_printf(MSG_DEBUG, "TLSv1: Failed to generate verify_data"); |
828 | 0 | tls_alert(conn, TLS_ALERT_LEVEL_FATAL, |
829 | 0 | TLS_ALERT_INTERNAL_ERROR); |
830 | 0 | return -1; |
831 | 0 | } |
832 | 0 | wpa_hexdump_key(MSG_DEBUG, "TLSv1: verify_data (client)", |
833 | 0 | verify_data + 1 + 3, TLS_VERIFY_DATA_LEN); |
834 | | |
835 | | /* Handshake */ |
836 | 0 | pos = hs_start = verify_data; |
837 | | /* HandshakeType msg_type */ |
838 | 0 | *pos++ = TLS_HANDSHAKE_TYPE_FINISHED; |
839 | | /* uint24 length */ |
840 | 0 | WPA_PUT_BE24(pos, TLS_VERIFY_DATA_LEN); |
841 | 0 | pos += 3; |
842 | 0 | pos += TLS_VERIFY_DATA_LEN; /* verify_data already in place */ |
843 | 0 | tls_verify_hash_add(&conn->verify, hs_start, pos - hs_start); |
844 | |
|
845 | 0 | if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_HANDSHAKE, |
846 | 0 | *msgpos, end - *msgpos, hs_start, pos - hs_start, |
847 | 0 | &rlen) < 0) { |
848 | 0 | wpa_printf(MSG_DEBUG, "TLSv1: Failed to create a record"); |
849 | 0 | tls_alert(conn, TLS_ALERT_LEVEL_FATAL, |
850 | 0 | TLS_ALERT_INTERNAL_ERROR); |
851 | 0 | return -1; |
852 | 0 | } |
853 | | |
854 | 0 | *msgpos += rlen; |
855 | |
|
856 | 0 | return 0; |
857 | 0 | } |
858 | | |
859 | | |
860 | | static u8 * tls_send_client_key_exchange(struct tlsv1_client *conn, |
861 | | size_t *out_len) |
862 | 0 | { |
863 | 0 | u8 *msg, *end, *pos; |
864 | 0 | size_t msglen; |
865 | |
|
866 | 0 | *out_len = 0; |
867 | |
|
868 | 0 | msglen = 2000; |
869 | 0 | if (conn->certificate_requested) |
870 | 0 | msglen += tls_client_cert_chain_der_len(conn); |
871 | |
|
872 | 0 | msg = os_malloc(msglen); |
873 | 0 | if (msg == NULL) |
874 | 0 | return NULL; |
875 | | |
876 | 0 | pos = msg; |
877 | 0 | end = msg + msglen; |
878 | |
|
879 | 0 | if (conn->certificate_requested) { |
880 | 0 | if (tls_write_client_certificate(conn, &pos, end) < 0) { |
881 | 0 | os_free(msg); |
882 | 0 | return NULL; |
883 | 0 | } |
884 | 0 | } |
885 | | |
886 | 0 | if (tls_write_client_key_exchange(conn, &pos, end) < 0 || |
887 | 0 | (conn->certificate_requested && conn->cred && conn->cred->key && |
888 | 0 | tls_write_client_certificate_verify(conn, &pos, end) < 0) || |
889 | 0 | tls_write_client_change_cipher_spec(conn, &pos, end) < 0 || |
890 | 0 | tls_write_client_finished(conn, &pos, end) < 0) { |
891 | 0 | os_free(msg); |
892 | 0 | return NULL; |
893 | 0 | } |
894 | | |
895 | 0 | *out_len = pos - msg; |
896 | |
|
897 | 0 | conn->state = SERVER_CHANGE_CIPHER_SPEC; |
898 | |
|
899 | 0 | return msg; |
900 | 0 | } |
901 | | |
902 | | |
903 | | static u8 * tls_send_change_cipher_spec(struct tlsv1_client *conn, |
904 | | size_t *out_len) |
905 | 0 | { |
906 | 0 | u8 *msg, *end, *pos; |
907 | |
|
908 | 0 | *out_len = 0; |
909 | |
|
910 | 0 | msg = os_malloc(1000); |
911 | 0 | if (msg == NULL) |
912 | 0 | return NULL; |
913 | | |
914 | 0 | pos = msg; |
915 | 0 | end = msg + 1000; |
916 | |
|
917 | 0 | if (tls_write_client_change_cipher_spec(conn, &pos, end) < 0 || |
918 | 0 | tls_write_client_finished(conn, &pos, end) < 0) { |
919 | 0 | os_free(msg); |
920 | 0 | return NULL; |
921 | 0 | } |
922 | | |
923 | 0 | *out_len = pos - msg; |
924 | |
|
925 | 0 | wpa_printf(MSG_DEBUG, "TLSv1: Session resumption completed " |
926 | 0 | "successfully"); |
927 | 0 | if (!conn->session_resumed && conn->use_session_ticket) |
928 | 0 | conn->session_resumed = 1; |
929 | 0 | conn->state = ESTABLISHED; |
930 | |
|
931 | 0 | return msg; |
932 | 0 | } |
933 | | |
934 | | |
935 | | u8 * tlsv1_client_handshake_write(struct tlsv1_client *conn, size_t *out_len, |
936 | | int no_appl_data) |
937 | 0 | { |
938 | 0 | switch (conn->state) { |
939 | 0 | case CLIENT_KEY_EXCHANGE: |
940 | 0 | return tls_send_client_key_exchange(conn, out_len); |
941 | 0 | case CHANGE_CIPHER_SPEC: |
942 | 0 | return tls_send_change_cipher_spec(conn, out_len); |
943 | 0 | case ACK_FINISHED: |
944 | 0 | wpa_printf(MSG_DEBUG, "TLSv1: Handshake completed " |
945 | 0 | "successfully"); |
946 | 0 | conn->state = ESTABLISHED; |
947 | 0 | *out_len = 0; |
948 | 0 | if (no_appl_data) { |
949 | | /* Need to return something to get final TLS ACK. */ |
950 | 0 | return os_malloc(1); |
951 | 0 | } |
952 | 0 | return NULL; |
953 | 0 | default: |
954 | 0 | wpa_printf(MSG_DEBUG, "TLSv1: Unexpected state %d while " |
955 | 0 | "generating reply", conn->state); |
956 | 0 | return NULL; |
957 | 0 | } |
958 | 0 | } |
959 | | |
960 | | |
961 | | u8 * tlsv1_client_send_alert(struct tlsv1_client *conn, u8 level, |
962 | | u8 description, size_t *out_len) |
963 | 0 | { |
964 | 0 | u8 *alert, *pos, *length; |
965 | |
|
966 | 0 | wpa_printf(MSG_DEBUG, "TLSv1: Send Alert(%d:%d)", level, description); |
967 | 0 | *out_len = 0; |
968 | |
|
969 | 0 | alert = os_malloc(10); |
970 | 0 | if (alert == NULL) |
971 | 0 | return NULL; |
972 | | |
973 | 0 | pos = alert; |
974 | | |
975 | | /* TLSPlaintext */ |
976 | | /* ContentType type */ |
977 | 0 | *pos++ = TLS_CONTENT_TYPE_ALERT; |
978 | | /* ProtocolVersion version */ |
979 | 0 | WPA_PUT_BE16(pos, conn->rl.tls_version ? conn->rl.tls_version : |
980 | 0 | TLS_VERSION); |
981 | 0 | pos += 2; |
982 | | /* uint16 length (to be filled) */ |
983 | 0 | length = pos; |
984 | 0 | pos += 2; |
985 | | /* opaque fragment[TLSPlaintext.length] */ |
986 | | |
987 | | /* Alert */ |
988 | | /* AlertLevel level */ |
989 | 0 | *pos++ = level; |
990 | | /* AlertDescription description */ |
991 | 0 | *pos++ = description; |
992 | |
|
993 | 0 | WPA_PUT_BE16(length, pos - length - 2); |
994 | 0 | *out_len = pos - alert; |
995 | |
|
996 | 0 | return alert; |
997 | 0 | } |