]>
Commit | Line | Data |
---|---|---|
4c0c2283 | 1 | /* |
dc9f6c68 | 2 | * Copyright (C) 2020-2021 Pascal Knecht |
7fbe2e27 PK |
3 | * HSR Hochschule fuer Technik Rapperswil |
4 | * | |
4c0c2283 MW |
5 | * Copyright (C) 2010 Martin Willi |
6 | * Copyright (C) 2010 revosec AG | |
7 | * | |
8 | * This program is free software; you can redistribute it and/or modify it | |
9 | * under the terms of the GNU General Public License as published by the | |
10 | * Free Software Foundation; either version 2 of the License, or (at your | |
11 | * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. | |
12 | * | |
13 | * This program is distributed in the hope that it will be useful, but | |
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY | |
15 | * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
16 | * for more details. | |
17 | */ | |
18 | ||
19 | #include "tls_server.h" | |
20 | ||
400df4ca MW |
21 | #include <time.h> |
22 | ||
f05b4272 | 23 | #include <utils/debug.h> |
714d0bfd | 24 | #include <credentials/certificates/x509.h> |
3767a4a6 | 25 | #include <collections/array.h> |
4c0c2283 MW |
26 | |
27 | typedef struct private_tls_server_t private_tls_server_t; | |
28 | ||
6a5c86b7 MW |
29 | /** |
30 | * Size of a session ID | |
31 | */ | |
32 | #define SESSION_ID_SIZE 16 | |
400df4ca MW |
33 | |
34 | typedef enum { | |
35 | STATE_INIT, | |
36 | STATE_HELLO_RECEIVED, | |
37 | STATE_HELLO_SENT, | |
38 | STATE_CERT_SENT, | |
f14358a9 | 39 | STATE_KEY_EXCHANGE_SENT, |
400df4ca MW |
40 | STATE_CERTREQ_SENT, |
41 | STATE_HELLO_DONE, | |
42 | STATE_CERT_RECEIVED, | |
43 | STATE_KEY_EXCHANGE_RECEIVED, | |
44 | STATE_CERT_VERIFY_RECEIVED, | |
45 | STATE_CIPHERSPEC_CHANGED_IN, | |
46 | STATE_FINISHED_RECEIVED, | |
47 | STATE_CIPHERSPEC_CHANGED_OUT, | |
48 | STATE_FINISHED_SENT, | |
7fbe2e27 PK |
49 | /* new states in TLS 1.3 */ |
50 | STATE_ENCRYPTED_EXTENSIONS_SENT, | |
51 | STATE_CERT_VERIFY_SENT, | |
ab70f68c PK |
52 | STATE_KEY_UPDATE_REQUESTED, |
53 | STATE_KEY_UPDATE_SENT, | |
d2fc9b09 | 54 | STATE_FINISHED_SENT_KEY_SWITCHED, |
400df4ca MW |
55 | } server_state_t; |
56 | ||
4c0c2283 MW |
57 | /** |
58 | * Private data of an tls_server_t object. | |
59 | */ | |
60 | struct private_tls_server_t { | |
61 | ||
62 | /** | |
63 | * Public tls_server_t interface. | |
64 | */ | |
65 | tls_server_t public; | |
536dbc00 | 66 | |
3e962b08 MW |
67 | /** |
68 | * TLS stack | |
69 | */ | |
70 | tls_t *tls; | |
71 | ||
536dbc00 MW |
72 | /** |
73 | * TLS crypto context | |
74 | */ | |
75 | tls_crypto_t *crypto; | |
3ddd164e | 76 | |
e6f3ef13 MW |
77 | /** |
78 | * TLS alert handler | |
79 | */ | |
80 | tls_alert_t *alert; | |
81 | ||
3ddd164e MW |
82 | /** |
83 | * Server identity | |
84 | */ | |
85 | identification_t *server; | |
86 | ||
87 | /** | |
69e8bb2e | 88 | * Peer identity, NULL for no client authentication |
3ddd164e MW |
89 | */ |
90 | identification_t *peer; | |
400df4ca MW |
91 | |
92 | /** | |
93 | * State we are in | |
94 | */ | |
95 | server_state_t state; | |
96 | ||
97 | /** | |
98 | * Hello random data selected by client | |
99 | */ | |
100 | char client_random[32]; | |
101 | ||
102 | /** | |
103 | * Hello random data selected by server | |
104 | */ | |
105 | char server_random[32]; | |
106 | ||
107 | /** | |
108 | * Auth helper for peer authentication | |
109 | */ | |
110 | auth_cfg_t *peer_auth; | |
111 | ||
112 | /** | |
113 | * Auth helper for server authentication | |
114 | */ | |
115 | auth_cfg_t *server_auth; | |
116 | ||
117 | /** | |
118 | * Peer private key | |
119 | */ | |
120 | private_key_t *private; | |
121 | ||
f14358a9 MW |
122 | /** |
123 | * DHE exchange | |
124 | */ | |
125 | diffie_hellman_t *dh; | |
126 | ||
7fbe2e27 PK |
127 | /** |
128 | * Requested DH group | |
129 | */ | |
130 | tls_named_group_t requested_curve; | |
131 | ||
400df4ca MW |
132 | /** |
133 | * Selected TLS cipher suite | |
134 | */ | |
135 | tls_cipher_suite_t suite; | |
60c4b3b5 MW |
136 | |
137 | /** | |
138 | * Offered TLS version of the client | |
139 | */ | |
140 | tls_version_t client_version; | |
06109c47 | 141 | |
6a5c86b7 MW |
142 | /** |
143 | * TLS session identifier | |
144 | */ | |
145 | chunk_t session; | |
146 | ||
147 | /** | |
148 | * Do we resume a session? | |
149 | */ | |
150 | bool resume; | |
151 | ||
06109c47 MW |
152 | /** |
153 | * Hash and signature algorithms supported by peer | |
154 | */ | |
155 | chunk_t hashsig; | |
37a59a8f MW |
156 | |
157 | /** | |
158 | * Elliptic curves supported by peer | |
159 | */ | |
160 | chunk_t curves; | |
161 | ||
162 | /** | |
163 | * Did we receive the curves from the client? | |
164 | */ | |
165 | bool curves_received; | |
a4a128bd SL |
166 | |
167 | /** | |
168 | * Whether to include CAs in CertificateRequest messages | |
169 | */ | |
170 | bool send_certreq_authorities; | |
4c0c2283 MW |
171 | }; |
172 | ||
4635f348 PK |
173 | /** |
174 | * Find a trusted public key to encrypt/verify key exchange data | |
175 | */ | |
176 | public_key_t *tls_find_public_key(auth_cfg_t *peer_auth) | |
177 | { | |
178 | public_key_t *public = NULL, *current; | |
179 | certificate_t *cert, *found; | |
180 | enumerator_t *enumerator; | |
181 | auth_cfg_t *auth; | |
182 | ||
183 | cert = peer_auth->get(peer_auth, AUTH_HELPER_SUBJECT_CERT); | |
184 | if (cert) | |
185 | { | |
186 | enumerator = lib->credmgr->create_public_enumerator(lib->credmgr, | |
187 | KEY_ANY, cert->get_subject(cert), | |
188 | peer_auth, TRUE); | |
189 | while (enumerator->enumerate(enumerator, ¤t, &auth)) | |
190 | { | |
191 | found = auth->get(auth, AUTH_RULE_SUBJECT_CERT); | |
192 | if (found && cert->equals(cert, found)) | |
193 | { | |
194 | public = current->get_ref(current); | |
195 | peer_auth->merge(peer_auth, auth, FALSE); | |
196 | break; | |
197 | } | |
198 | } | |
199 | enumerator->destroy(enumerator); | |
200 | } | |
201 | return public; | |
202 | } | |
203 | ||
4cdade5a MW |
204 | /** |
205 | * Find a cipher suite and a server key | |
206 | */ | |
207 | static bool select_suite_and_key(private_tls_server_t *this, | |
208 | tls_cipher_suite_t *suites, int count) | |
209 | { | |
9803fb82 | 210 | tls_version_t version_min, version_max; |
4cdade5a | 211 | private_key_t *key; |
d8e42a3d PK |
212 | auth_cfg_t *auth; |
213 | enumerator_t *enumerator; | |
4cdade5a | 214 | |
9803fb82 PK |
215 | version_min = this->tls->get_version_min(this->tls); |
216 | version_max = this->tls->get_version_max(this->tls); | |
d8e42a3d PK |
217 | enumerator = tls_create_private_key_enumerator(version_min, version_max, |
218 | this->hashsig, this->server); | |
219 | if (!enumerator) | |
9803fb82 PK |
220 | { |
221 | DBG1(DBG_TLS, "no common signature algorithms found"); | |
9803fb82 PK |
222 | return FALSE; |
223 | } | |
d8e42a3d | 224 | if (!enumerator->enumerate(enumerator, &key, &auth)) |
4cdade5a MW |
225 | { |
226 | DBG1(DBG_TLS, "no usable TLS server certificate found for '%Y'", | |
227 | this->server); | |
d8e42a3d | 228 | enumerator->destroy(enumerator); |
4cdade5a MW |
229 | return FALSE; |
230 | } | |
4cdade5a | 231 | |
9803fb82 | 232 | if (version_max >= TLS_1_3) |
7fbe2e27 | 233 | { |
7fbe2e27 PK |
234 | this->suite = this->crypto->select_cipher_suite(this->crypto, suites, |
235 | count, KEY_ANY); | |
7fbe2e27 PK |
236 | } |
237 | else | |
238 | { | |
239 | this->suite = this->crypto->select_cipher_suite(this->crypto, suites, | |
d8e42a3d PK |
240 | count, key->get_type(key)); |
241 | while (!this->suite && | |
242 | enumerator->enumerate(enumerator, &key, &auth)) | |
9803fb82 | 243 | { /* find a key and cipher suite for one of the remaining key types */ |
d8e42a3d PK |
244 | this->suite = this->crypto->select_cipher_suite(this->crypto, |
245 | suites, count, | |
246 | key->get_type(key)); | |
4cdade5a MW |
247 | } |
248 | } | |
d8e42a3d | 249 | if (!this->suite) |
9803fb82 PK |
250 | { |
251 | DBG1(DBG_TLS, "received cipher suites or signature schemes unacceptable"); | |
d8e42a3d | 252 | enumerator->destroy(enumerator); |
9803fb82 PK |
253 | return FALSE; |
254 | } | |
255 | DBG1(DBG_TLS, "using key of type %N", key_type_names, key->get_type(key)); | |
ab226b39 | 256 | DESTROY_IF(this->private); |
d8e42a3d | 257 | this->private = key->get_ref(key); |
ab226b39 | 258 | this->server_auth->purge(this->server_auth, FALSE); |
d8e42a3d PK |
259 | this->server_auth->merge(this->server_auth, auth, FALSE); |
260 | enumerator->destroy(enumerator); | |
4cdade5a MW |
261 | return TRUE; |
262 | } | |
263 | ||
7fbe2e27 PK |
264 | /** |
265 | * Check if the peer supports a given TLS curve | |
266 | */ | |
267 | static bool peer_supports_curve(private_tls_server_t *this, | |
268 | tls_named_group_t curve) | |
269 | { | |
270 | bio_reader_t *reader; | |
271 | uint16_t current; | |
272 | ||
273 | if (!this->curves_received) | |
274 | { /* none received, assume yes */ | |
275 | return TRUE; | |
276 | } | |
277 | reader = bio_reader_create(this->curves); | |
278 | while (reader->remaining(reader) && reader->read_uint16(reader, ¤t)) | |
279 | { | |
280 | if (current == curve) | |
281 | { | |
282 | reader->destroy(reader); | |
283 | return TRUE; | |
284 | } | |
285 | } | |
286 | reader->destroy(reader); | |
287 | return FALSE; | |
288 | } | |
289 | ||
3767a4a6 PK |
290 | /** |
291 | * TLS 1.3 key exchange key share | |
292 | */ | |
293 | typedef struct { | |
294 | uint16_t curve; | |
295 | chunk_t key_share; | |
296 | } key_share_t; | |
297 | ||
298 | /** | |
299 | * Check if peer sent a key share of a given TLS named DH group | |
300 | */ | |
301 | static bool peer_offered_curve(array_t *key_shares, tls_named_group_t curve, | |
302 | key_share_t *out) | |
303 | { | |
304 | key_share_t peer; | |
305 | int i; | |
306 | ||
307 | for (i = 0; i < array_count(key_shares); i++) | |
308 | { | |
309 | array_get(key_shares, i, &peer); | |
310 | if (curve == peer.curve) | |
311 | { | |
312 | if (out) | |
313 | { | |
314 | *out = peer; | |
315 | } | |
316 | return TRUE; | |
317 | } | |
318 | } | |
319 | return FALSE; | |
320 | } | |
321 | ||
c3e71324 PK |
322 | /** |
323 | * Check if client is currently retrying to connect to the server. | |
324 | */ | |
325 | static bool retrying(private_tls_server_t *this) | |
326 | { | |
327 | return this->state == STATE_INIT && this->requested_curve; | |
328 | } | |
329 | ||
400df4ca MW |
330 | /** |
331 | * Process client hello message | |
332 | */ | |
333 | static status_t process_client_hello(private_tls_server_t *this, | |
7e432eff | 334 | bio_reader_t *reader) |
400df4ca | 335 | { |
3767a4a6 | 336 | uint16_t legacy_version = 0, version = 0, extension_type = 0; |
7fbe2e27 | 337 | chunk_t random, session, ciphers, versions = chunk_empty, compression; |
3767a4a6 PK |
338 | chunk_t ext = chunk_empty, key_shares = chunk_empty; |
339 | key_share_t peer = {0}; | |
7fbe2e27 PK |
340 | chunk_t extension_data = chunk_empty; |
341 | bio_reader_t *extensions, *extension; | |
400df4ca | 342 | tls_cipher_suite_t *suites; |
dc9f6c68 | 343 | tls_version_t original_version_max; |
400df4ca | 344 | int count, i; |
6a5c86b7 | 345 | rng_t *rng; |
400df4ca MW |
346 | |
347 | this->crypto->append_handshake(this->crypto, | |
348 | TLS_CLIENT_HELLO, reader->peek(reader)); | |
349 | ||
7fbe2e27 | 350 | if (!reader->read_uint16(reader, &legacy_version) || |
400df4ca MW |
351 | !reader->read_data(reader, sizeof(this->client_random), &random) || |
352 | !reader->read_data8(reader, &session) || | |
353 | !reader->read_data16(reader, &ciphers) || | |
354 | !reader->read_data8(reader, &compression) || | |
355 | (reader->remaining(reader) && !reader->read_data16(reader, &ext))) | |
356 | { | |
3c19b346 | 357 | DBG1(DBG_TLS, "received invalid ClientHello"); |
e6f3ef13 MW |
358 | this->alert->add(this->alert, TLS_FATAL, TLS_DECODE_ERROR); |
359 | return NEED_MORE; | |
400df4ca MW |
360 | } |
361 | ||
06424efa TB |
362 | /* before we do anything version-related, determine our supported suites |
363 | * as that might change the min./max. versions */ | |
364 | this->crypto->get_cipher_suites(this->crypto, NULL); | |
365 | ||
7fbe2e27 PK |
366 | extensions = bio_reader_create(ext); |
367 | while (extensions->remaining(extensions)) | |
06109c47 | 368 | { |
7fbe2e27 PK |
369 | if (!extensions->read_uint16(extensions, &extension_type) || |
370 | !extensions->read_data16(extensions, &extension_data)) | |
06109c47 | 371 | { |
7fbe2e27 PK |
372 | DBG1(DBG_TLS, "received invalid ClientHello Extensions"); |
373 | this->alert->add(this->alert, TLS_FATAL, TLS_DECODE_ERROR); | |
374 | extensions->destroy(extensions); | |
375 | return NEED_MORE; | |
06109c47 | 376 | } |
7fbe2e27 PK |
377 | extension = bio_reader_create(extension_data); |
378 | DBG2(DBG_TLS, "received TLS '%N' extension", | |
379 | tls_extension_names, extension_type); | |
380 | DBG3(DBG_TLS, "%B", &extension_data); | |
381 | switch (extension_type) | |
382 | { | |
383 | case TLS_EXT_SIGNATURE_ALGORITHMS: | |
0dfe1590 PK |
384 | if (!extension->read_data16(extension, &extension_data)) |
385 | { | |
386 | DBG1(DBG_TLS, "invalid %N extension", | |
387 | tls_extension_names, extension_type); | |
388 | this->alert->add(this->alert, TLS_FATAL, TLS_DECODE_ERROR); | |
389 | extensions->destroy(extensions); | |
390 | extension->destroy(extension); | |
391 | return NEED_MORE; | |
392 | } | |
c3e71324 | 393 | chunk_free(&this->hashsig); |
7fbe2e27 PK |
394 | this->hashsig = chunk_clone(extension_data); |
395 | break; | |
396 | case TLS_EXT_SUPPORTED_GROUPS: | |
0dfe1590 PK |
397 | if (!extension->read_data16(extension, &extension_data)) |
398 | { | |
399 | DBG1(DBG_TLS, "invalid %N extension", | |
400 | tls_extension_names, extension_type); | |
401 | this->alert->add(this->alert, TLS_FATAL, TLS_DECODE_ERROR); | |
402 | extensions->destroy(extensions); | |
403 | extension->destroy(extension); | |
404 | return NEED_MORE; | |
405 | } | |
c3e71324 | 406 | chunk_free(&this->curves); |
7fbe2e27 PK |
407 | this->curves_received = TRUE; |
408 | this->curves = chunk_clone(extension_data); | |
409 | break; | |
410 | case TLS_EXT_SUPPORTED_VERSIONS: | |
411 | if (!extension->read_data8(extension, &versions)) | |
412 | { | |
413 | DBG1(DBG_TLS, "invalid %N extension", | |
414 | tls_extension_names, extension_type); | |
0dfe1590 | 415 | this->alert->add(this->alert, TLS_FATAL, TLS_DECODE_ERROR); |
7fbe2e27 PK |
416 | extensions->destroy(extensions); |
417 | extension->destroy(extension); | |
418 | return NEED_MORE; | |
419 | } | |
420 | break; | |
421 | case TLS_EXT_KEY_SHARE: | |
3767a4a6 | 422 | if (!extension->read_data16(extension, &key_shares)) |
7fbe2e27 PK |
423 | { |
424 | DBG1(DBG_TLS, "invalid %N extension", | |
425 | tls_extension_names, extension_type); | |
5c4cb40e | 426 | this->alert->add(this->alert, TLS_FATAL, TLS_DECODE_ERROR); |
7fbe2e27 PK |
427 | extensions->destroy(extensions); |
428 | extension->destroy(extension); | |
429 | return NEED_MORE; | |
430 | } | |
431 | break; | |
432 | default: | |
433 | break; | |
434 | } | |
435 | extension->destroy(extension); | |
06109c47 | 436 | } |
7fbe2e27 | 437 | extensions->destroy(extensions); |
06109c47 | 438 | |
e7313962 PK |
439 | if (this->tls->get_version_max(this->tls) >= TLS_1_3 && !this->hashsig.len) |
440 | { | |
441 | DBG1(DBG_TLS, "no %N extension received", tls_extension_names, | |
442 | TLS_MISSING_EXTENSION); | |
443 | this->alert->add(this->alert, TLS_FATAL, TLS_MISSING_EXTENSION); | |
444 | return NEED_MORE; | |
445 | } | |
446 | ||
400df4ca MW |
447 | memcpy(this->client_random, random.ptr, sizeof(this->client_random)); |
448 | ||
6a5c86b7 MW |
449 | htoun32(&this->server_random, time(NULL)); |
450 | rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK); | |
126eb2af TB |
451 | if (!rng || |
452 | !rng->get_bytes(rng, sizeof(this->server_random) - 4, | |
453 | this->server_random + 4)) | |
6a5c86b7 | 454 | { |
126eb2af | 455 | DBG1(DBG_TLS, "failed to generate server random"); |
6a5c86b7 | 456 | this->alert->add(this->alert, TLS_FATAL, TLS_INTERNAL_ERROR); |
126eb2af | 457 | DESTROY_IF(rng); |
6a5c86b7 MW |
458 | return NEED_MORE; |
459 | } | |
6a5c86b7 MW |
460 | rng->destroy(rng); |
461 | ||
dc9f6c68 PK |
462 | original_version_max = this->tls->get_version_max(this->tls); |
463 | ||
7fbe2e27 PK |
464 | if (versions.len) |
465 | { | |
466 | bio_reader_t *client_versions; | |
467 | ||
468 | client_versions = bio_reader_create(versions); | |
469 | while (client_versions->remaining(client_versions)) | |
470 | { | |
471 | if (client_versions->read_uint16(client_versions, &version)) | |
472 | { | |
473 | if (this->tls->set_version(this->tls, version, version)) | |
474 | { | |
475 | this->client_version = version; | |
476 | break; | |
477 | } | |
478 | } | |
479 | } | |
480 | client_versions->destroy(client_versions); | |
481 | } | |
482 | else | |
483 | { | |
484 | version = legacy_version; | |
485 | if (this->tls->set_version(this->tls, version, version)) | |
486 | { | |
487 | this->client_version = version; | |
488 | } | |
489 | } | |
dc9f6c68 PK |
490 | |
491 | /* downgrade protection (see RFC 8446, section 4.1.3) */ | |
492 | if ((original_version_max == TLS_1_3 && version < TLS_1_3) || | |
493 | (original_version_max == TLS_1_2 && version < TLS_1_2)) | |
494 | { | |
495 | chunk_t downgrade_protection = tls_downgrade_protection_tls11; | |
496 | ||
497 | if (version == TLS_1_2) | |
498 | { | |
499 | downgrade_protection = tls_downgrade_protection_tls12; | |
500 | } | |
501 | memcpy(&this->server_random[24], downgrade_protection.ptr, | |
502 | downgrade_protection.len); | |
503 | } | |
504 | ||
7fbe2e27 | 505 | if (!this->client_version) |
400df4ca | 506 | { |
7fbe2e27 PK |
507 | DBG1(DBG_TLS, "proposed version %N not supported", tls_version_names, |
508 | version); | |
e6f3ef13 MW |
509 | this->alert->add(this->alert, TLS_FATAL, TLS_PROTOCOL_VERSION); |
510 | return NEED_MORE; | |
400df4ca | 511 | } |
6a5c86b7 | 512 | |
7fbe2e27 PK |
513 | if (this->tls->get_version_max(this->tls) < TLS_1_3) |
514 | { | |
515 | this->suite = this->crypto->resume_session(this->crypto, session, | |
516 | this->peer, | |
517 | chunk_from_thing(this->client_random), | |
518 | chunk_from_thing(this->server_random)); | |
519 | } | |
520 | ||
ab226b39 | 521 | if (this->suite && !retrying(this)) |
400df4ca | 522 | { |
6a5c86b7 MW |
523 | this->session = chunk_clone(session); |
524 | this->resume = TRUE; | |
525 | DBG1(DBG_TLS, "resumed %N using suite %N", | |
7a2b0266 | 526 | tls_version_names, this->tls->get_version_max(this->tls), |
6a5c86b7 | 527 | tls_cipher_suite_names, this->suite); |
400df4ca | 528 | } |
6a5c86b7 | 529 | else |
400df4ca | 530 | { |
ab226b39 TB |
531 | tls_cipher_suite_t original_suite = this->suite; |
532 | ||
b12c53ce | 533 | count = ciphers.len / sizeof(uint16_t); |
6a5c86b7 MW |
534 | suites = alloca(count * sizeof(tls_cipher_suite_t)); |
535 | DBG2(DBG_TLS, "received %d TLS cipher suites:", count); | |
536 | for (i = 0; i < count; i++) | |
537 | { | |
b12c53ce | 538 | suites[i] = untoh16(&ciphers.ptr[i * sizeof(uint16_t)]); |
6a5c86b7 MW |
539 | DBG2(DBG_TLS, " %N", tls_cipher_suite_names, suites[i]); |
540 | } | |
541 | if (!select_suite_and_key(this, suites, count)) | |
542 | { | |
543 | this->alert->add(this->alert, TLS_FATAL, TLS_HANDSHAKE_FAILURE); | |
544 | return NEED_MORE; | |
545 | } | |
ab226b39 TB |
546 | if (retrying(this) && original_suite != this->suite) |
547 | { | |
548 | DBG1(DBG_TLS, "selected %N instead of %N during retry", | |
549 | tls_cipher_suite_names, this->suite, tls_cipher_suite_names, | |
550 | original_suite); | |
551 | this->alert->add(this->alert, TLS_FATAL, TLS_ILLEGAL_PARAMETER); | |
552 | return NEED_MORE; | |
553 | } | |
7fbe2e27 | 554 | if (this->tls->get_version_max(this->tls) < TLS_1_3) |
6a5c86b7 | 555 | { |
7fbe2e27 PK |
556 | rng = lib->crypto->create_rng(lib->crypto, RNG_STRONG); |
557 | if (!rng || | |
558 | !rng->allocate_bytes(rng, SESSION_ID_SIZE, &this->session)) | |
559 | { | |
560 | DBG1(DBG_TLS, "generating TLS session identifier failed, skipped"); | |
561 | } | |
562 | DESTROY_IF(rng); | |
563 | } | |
564 | else | |
565 | { | |
ab226b39 | 566 | chunk_free(&this->session); |
7fbe2e27 | 567 | this->session = chunk_clone(session); |
6a5c86b7 MW |
568 | } |
569 | DBG1(DBG_TLS, "negotiated %N using suite %N", | |
7a2b0266 | 570 | tls_version_names, this->tls->get_version_max(this->tls), |
6a5c86b7 | 571 | tls_cipher_suite_names, this->suite); |
400df4ca | 572 | } |
7fbe2e27 PK |
573 | |
574 | if (this->tls->get_version_max(this->tls) >= TLS_1_3) | |
575 | { | |
576 | diffie_hellman_group_t group; | |
c3e71324 | 577 | tls_named_group_t curve, requesting_curve = 0; |
7fbe2e27 | 578 | enumerator_t *enumerator; |
3767a4a6 PK |
579 | array_t *peer_key_shares; |
580 | ||
581 | peer_key_shares = array_create(sizeof(key_share_t), 1); | |
582 | extension = bio_reader_create(key_shares); | |
583 | while (extension->remaining(extension)) | |
584 | { | |
585 | if (!extension->read_uint16(extension, &peer.curve) || | |
586 | !extension->read_data16(extension, &peer.key_share) || | |
587 | !peer.key_share.len) | |
588 | { | |
589 | DBG1(DBG_TLS, "invalid %N extension", | |
590 | tls_extension_names, extension_type); | |
591 | this->alert->add(this->alert, TLS_FATAL, TLS_DECODE_ERROR); | |
592 | extension->destroy(extension); | |
593 | array_destroy(peer_key_shares); | |
594 | return NEED_MORE; | |
595 | } | |
596 | array_insert(peer_key_shares, ARRAY_TAIL, &peer); | |
597 | } | |
598 | extension->destroy(extension); | |
7fbe2e27 PK |
599 | |
600 | enumerator = this->crypto->create_ec_enumerator(this->crypto); | |
601 | while (enumerator->enumerate(enumerator, &group, &curve)) | |
602 | { | |
c3e71324 | 603 | if (!requesting_curve && |
3767a4a6 PK |
604 | peer_supports_curve(this, curve) && |
605 | !peer_offered_curve(peer_key_shares, curve, NULL)) | |
c3e71324 PK |
606 | { |
607 | requesting_curve = curve; | |
608 | } | |
3767a4a6 PK |
609 | if (peer_supports_curve(this, curve) && |
610 | peer_offered_curve(peer_key_shares, curve, &peer)) | |
7fbe2e27 | 611 | { |
c3e71324 PK |
612 | DBG1(DBG_TLS, "using key exchange %N", |
613 | tls_named_group_names, curve); | |
7fbe2e27 PK |
614 | this->dh = lib->crypto->create_dh(lib->crypto, group); |
615 | break; | |
616 | } | |
617 | } | |
618 | enumerator->destroy(enumerator); | |
3767a4a6 | 619 | array_destroy(peer_key_shares); |
c3e71324 | 620 | |
7fbe2e27 | 621 | if (!this->dh) |
c3e71324 PK |
622 | { |
623 | if (retrying(this)) | |
624 | { | |
625 | DBG1(DBG_TLS, "already replied with a hello retry request"); | |
626 | this->alert->add(this->alert, TLS_FATAL, TLS_UNEXPECTED_MESSAGE); | |
627 | return NEED_MORE; | |
628 | } | |
629 | ||
c3e71324 PK |
630 | if (!requesting_curve) |
631 | { | |
632 | DBG1(DBG_TLS, "no mutual supported group in client hello"); | |
633 | this->alert->add(this->alert, TLS_FATAL, TLS_ILLEGAL_PARAMETER); | |
634 | return NEED_MORE; | |
635 | } | |
636 | this->requested_curve = requesting_curve; | |
7fbe2e27 | 637 | |
c3e71324 | 638 | if (!this->crypto->hash_handshake(this->crypto, NULL)) |
7fbe2e27 | 639 | { |
c3e71324 | 640 | DBG1(DBG_TLS, "failed to hash handshake messages"); |
7fbe2e27 PK |
641 | this->alert->add(this->alert, TLS_FATAL, TLS_INTERNAL_ERROR); |
642 | return NEED_MORE; | |
643 | } | |
7fbe2e27 | 644 | } |
c3e71324 | 645 | else |
7fbe2e27 | 646 | { |
3767a4a6 PK |
647 | if (peer.key_share.len && |
648 | peer.curve != TLS_CURVE25519 && | |
649 | peer.curve != TLS_CURVE448) | |
c3e71324 | 650 | { /* classic format (see RFC 8446, section 4.2.8.2) */ |
3767a4a6 | 651 | if (peer.key_share.ptr[0] != TLS_ANSI_UNCOMPRESSED) |
c3e71324 PK |
652 | { |
653 | DBG1(DBG_TLS, "DH point format '%N' not supported", | |
3767a4a6 | 654 | tls_ansi_point_format_names, peer.key_share.ptr[0]); |
c3e71324 PK |
655 | this->alert->add(this->alert, TLS_FATAL, TLS_INTERNAL_ERROR); |
656 | return NEED_MORE; | |
657 | } | |
3767a4a6 | 658 | peer.key_share = chunk_skip(peer.key_share, 1); |
c3e71324 | 659 | } |
3767a4a6 PK |
660 | if (!peer.key_share.len || |
661 | !this->dh->set_other_public_value(this->dh, peer.key_share)) | |
c3e71324 PK |
662 | { |
663 | DBG1(DBG_TLS, "DH key derivation failed"); | |
664 | this->alert->add(this->alert, TLS_FATAL, TLS_HANDSHAKE_FAILURE); | |
c3e71324 PK |
665 | return NEED_MORE; |
666 | } | |
c3e71324 | 667 | this->requested_curve = 0; |
7fbe2e27 | 668 | } |
7fbe2e27 PK |
669 | } |
670 | ||
400df4ca MW |
671 | this->state = STATE_HELLO_RECEIVED; |
672 | return NEED_MORE; | |
673 | } | |
674 | ||
675 | /** | |
676 | * Process certificate | |
677 | */ | |
678 | static status_t process_certificate(private_tls_server_t *this, | |
7e432eff | 679 | bio_reader_t *reader) |
400df4ca MW |
680 | { |
681 | certificate_t *cert; | |
7e432eff | 682 | bio_reader_t *certs; |
400df4ca MW |
683 | chunk_t data; |
684 | bool first = TRUE; | |
685 | ||
686 | this->crypto->append_handshake(this->crypto, | |
687 | TLS_CERTIFICATE, reader->peek(reader)); | |
688 | ||
d2fc9b09 PK |
689 | if (this->tls->get_version_max(this->tls) > TLS_1_2) |
690 | { | |
691 | if (!reader->read_data8(reader, &data)) | |
692 | { | |
693 | DBG1(DBG_TLS, "certificate request context invalid"); | |
694 | this->alert->add(this->alert, TLS_FATAL, TLS_DECODE_ERROR); | |
695 | return NEED_MORE; | |
696 | } | |
697 | } | |
698 | ||
400df4ca MW |
699 | if (!reader->read_data24(reader, &data)) |
700 | { | |
e6f3ef13 MW |
701 | DBG1(DBG_TLS, "certificate message header invalid"); |
702 | this->alert->add(this->alert, TLS_FATAL, TLS_DECODE_ERROR); | |
703 | return NEED_MORE; | |
400df4ca | 704 | } |
7e432eff | 705 | certs = bio_reader_create(data); |
dc49d457 PK |
706 | if (!certs->remaining(certs)) |
707 | { | |
760f3b73 TB |
708 | if (this->tls->get_flags(this->tls) & TLS_FLAG_CLIENT_AUTH_OPTIONAL) |
709 | { | |
710 | /* client authentication is not required so we clear the identity */ | |
711 | DESTROY_IF(this->peer); | |
712 | this->peer = NULL; | |
713 | } | |
714 | else | |
715 | { | |
716 | DBG1(DBG_TLS, "no certificate sent by peer"); | |
717 | this->alert->add(this->alert, TLS_FATAL, TLS_DECODE_ERROR); | |
718 | return NEED_MORE; | |
719 | } | |
dc49d457 | 720 | } |
400df4ca MW |
721 | while (certs->remaining(certs)) |
722 | { | |
723 | if (!certs->read_data24(certs, &data)) | |
724 | { | |
e6f3ef13 MW |
725 | DBG1(DBG_TLS, "certificate message invalid"); |
726 | this->alert->add(this->alert, TLS_FATAL, TLS_DECODE_ERROR); | |
400df4ca | 727 | certs->destroy(certs); |
e6f3ef13 | 728 | return NEED_MORE; |
400df4ca MW |
729 | } |
730 | cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509, | |
731 | BUILD_BLOB_ASN1_DER, data, BUILD_END); | |
732 | if (cert) | |
733 | { | |
734 | if (first) | |
735 | { | |
736 | this->peer_auth->add(this->peer_auth, | |
737 | AUTH_HELPER_SUBJECT_CERT, cert); | |
3c19b346 | 738 | DBG1(DBG_TLS, "received TLS peer certificate '%Y'", |
400df4ca MW |
739 | cert->get_subject(cert)); |
740 | first = FALSE; | |
4b7cfb25 TB |
741 | if (this->peer && this->peer->get_type(this->peer) == ID_ANY) |
742 | { | |
743 | this->peer->destroy(this->peer); | |
744 | this->peer = cert->get_subject(cert); | |
745 | this->peer = this->peer->clone(this->peer); | |
746 | } | |
400df4ca MW |
747 | } |
748 | else | |
749 | { | |
3c19b346 | 750 | DBG1(DBG_TLS, "received TLS intermediate certificate '%Y'", |
400df4ca MW |
751 | cert->get_subject(cert)); |
752 | this->peer_auth->add(this->peer_auth, AUTH_HELPER_IM_CERT, cert); | |
753 | } | |
754 | } | |
755 | else | |
756 | { | |
3c19b346 | 757 | DBG1(DBG_TLS, "parsing TLS certificate failed, skipped"); |
e6f3ef13 | 758 | this->alert->add(this->alert, TLS_WARNING, TLS_BAD_CERTIFICATE); |
400df4ca | 759 | } |
d2fc9b09 PK |
760 | if (this->tls->get_version_max(this->tls) > TLS_1_2) |
761 | { | |
762 | if (!certs->read_data16(certs, &data)) | |
763 | { | |
764 | DBG1(DBG_TLS, "failed to read extensions of CertificateEntry"); | |
765 | this->alert->add(this->alert, TLS_FATAL, TLS_DECODE_ERROR); | |
766 | return NEED_MORE; | |
767 | } | |
768 | } | |
400df4ca MW |
769 | } |
770 | certs->destroy(certs); | |
771 | this->state = STATE_CERT_RECEIVED; | |
772 | return NEED_MORE; | |
773 | } | |
774 | ||
775 | /** | |
f14358a9 | 776 | * Process Client Key Exchange, using premaster encryption |
400df4ca | 777 | */ |
f14358a9 | 778 | static status_t process_key_exchange_encrypted(private_tls_server_t *this, |
7e432eff | 779 | bio_reader_t *reader) |
400df4ca | 780 | { |
60c4b3b5 MW |
781 | chunk_t encrypted, decrypted; |
782 | char premaster[48]; | |
783 | rng_t *rng; | |
400df4ca MW |
784 | |
785 | this->crypto->append_handshake(this->crypto, | |
786 | TLS_CLIENT_KEY_EXCHANGE, reader->peek(reader)); | |
787 | ||
788 | if (!reader->read_data16(reader, &encrypted)) | |
789 | { | |
3c19b346 | 790 | DBG1(DBG_TLS, "received invalid Client Key Exchange"); |
e6f3ef13 MW |
791 | this->alert->add(this->alert, TLS_FATAL, TLS_DECODE_ERROR); |
792 | return NEED_MORE; | |
400df4ca MW |
793 | } |
794 | ||
60c4b3b5 MW |
795 | htoun16(premaster, this->client_version); |
796 | /* pre-randomize premaster for failure cases */ | |
797 | rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK); | |
126eb2af | 798 | if (!rng || !rng->get_bytes(rng, sizeof(premaster) - 2, premaster + 2)) |
400df4ca | 799 | { |
126eb2af | 800 | DBG1(DBG_TLS, "failed to generate premaster secret"); |
60c4b3b5 | 801 | this->alert->add(this->alert, TLS_FATAL, TLS_INTERNAL_ERROR); |
126eb2af | 802 | DESTROY_IF(rng); |
e6f3ef13 | 803 | return NEED_MORE; |
400df4ca | 804 | } |
60c4b3b5 MW |
805 | rng->destroy(rng); |
806 | ||
807 | if (this->private && | |
4abb29f6 AS |
808 | this->private->decrypt(this->private, ENCRYPT_RSA_PKCS1, NULL, |
809 | encrypted, &decrypted)) | |
60c4b3b5 MW |
810 | { |
811 | if (decrypted.len == sizeof(premaster) && | |
812 | untoh16(decrypted.ptr) == this->client_version) | |
813 | { | |
814 | memcpy(premaster + 2, decrypted.ptr + 2, sizeof(premaster) - 2); | |
815 | } | |
816 | else | |
817 | { | |
818 | DBG1(DBG_TLS, "decrypted premaster has invalid length/version"); | |
819 | } | |
820 | chunk_clear(&decrypted); | |
821 | } | |
822 | else | |
823 | { | |
824 | DBG1(DBG_TLS, "decrypting Client Key Exchange failed"); | |
825 | } | |
826 | ||
9020f7d0 MW |
827 | if (!this->crypto->derive_secrets(this->crypto, chunk_from_thing(premaster), |
828 | this->session, this->peer, | |
829 | chunk_from_thing(this->client_random), | |
830 | chunk_from_thing(this->server_random))) | |
831 | { | |
832 | this->alert->add(this->alert, TLS_FATAL, TLS_INTERNAL_ERROR); | |
833 | return NEED_MORE; | |
834 | } | |
400df4ca MW |
835 | |
836 | this->state = STATE_KEY_EXCHANGE_RECEIVED; | |
837 | return NEED_MORE; | |
838 | } | |
839 | ||
f14358a9 MW |
840 | /** |
841 | * Process client key exchange, using DHE exchange | |
842 | */ | |
843 | static status_t process_key_exchange_dhe(private_tls_server_t *this, | |
7e432eff | 844 | bio_reader_t *reader) |
f14358a9 MW |
845 | { |
846 | chunk_t premaster, pub; | |
966a26ea | 847 | diffie_hellman_group_t group; |
f4c98ae6 | 848 | bool ec; |
f14358a9 MW |
849 | |
850 | this->crypto->append_handshake(this->crypto, | |
851 | TLS_CLIENT_KEY_EXCHANGE, reader->peek(reader)); | |
852 | ||
966a26ea TB |
853 | group = this->dh->get_dh_group(this->dh); |
854 | ec = diffie_hellman_group_is_ec(group); | |
141d7f7a | 855 | if ((ec && !reader->read_data8(reader, &pub)) || |
e6cce7ff | 856 | (!ec && (!reader->read_data16(reader, &pub) || pub.len == 0))) |
f14358a9 MW |
857 | { |
858 | DBG1(DBG_TLS, "received invalid Client Key Exchange"); | |
859 | this->alert->add(this->alert, TLS_FATAL, TLS_DECODE_ERROR); | |
860 | return NEED_MORE; | |
861 | } | |
e6cce7ff | 862 | |
966a26ea TB |
863 | if (ec && |
864 | group != CURVE_25519 && | |
865 | group != CURVE_448) | |
e6cce7ff | 866 | { |
7b3c0184 MW |
867 | if (pub.ptr[0] != TLS_ANSI_UNCOMPRESSED) |
868 | { | |
869 | DBG1(DBG_TLS, "DH point format '%N' not supported", | |
870 | tls_ansi_point_format_names, pub.ptr[0]); | |
871 | this->alert->add(this->alert, TLS_FATAL, TLS_INTERNAL_ERROR); | |
872 | return NEED_MORE; | |
873 | } | |
874 | pub = chunk_skip(pub, 1); | |
e6cce7ff | 875 | } |
a777155f MW |
876 | if (!this->dh->set_other_public_value(this->dh, pub)) |
877 | { | |
878 | DBG1(DBG_TLS, "applying DH public value failed"); | |
879 | this->alert->add(this->alert, TLS_FATAL, TLS_INTERNAL_ERROR); | |
880 | return NEED_MORE; | |
881 | } | |
bace1d64 | 882 | if (!this->dh->get_shared_secret(this->dh, &premaster)) |
f14358a9 MW |
883 | { |
884 | DBG1(DBG_TLS, "calculating premaster from DH failed"); | |
885 | this->alert->add(this->alert, TLS_FATAL, TLS_INTERNAL_ERROR); | |
886 | return NEED_MORE; | |
887 | } | |
888 | ||
9020f7d0 MW |
889 | if (!this->crypto->derive_secrets(this->crypto, premaster, |
890 | this->session, this->peer, | |
891 | chunk_from_thing(this->client_random), | |
892 | chunk_from_thing(this->server_random))) | |
893 | { | |
894 | this->alert->add(this->alert, TLS_FATAL, TLS_INTERNAL_ERROR); | |
895 | chunk_clear(&premaster); | |
896 | return NEED_MORE; | |
897 | } | |
f14358a9 MW |
898 | chunk_clear(&premaster); |
899 | ||
900 | this->state = STATE_KEY_EXCHANGE_RECEIVED; | |
901 | return NEED_MORE; | |
902 | } | |
903 | ||
904 | /** | |
905 | * Process Client Key Exchange | |
906 | */ | |
907 | static status_t process_key_exchange(private_tls_server_t *this, | |
7e432eff | 908 | bio_reader_t *reader) |
f14358a9 MW |
909 | { |
910 | if (this->dh) | |
911 | { | |
912 | return process_key_exchange_dhe(this, reader); | |
913 | } | |
914 | return process_key_exchange_encrypted(this, reader); | |
915 | } | |
916 | ||
400df4ca MW |
917 | /** |
918 | * Process Certificate verify | |
919 | */ | |
920 | static status_t process_cert_verify(private_tls_server_t *this, | |
7e432eff | 921 | bio_reader_t *reader) |
400df4ca | 922 | { |
400df4ca | 923 | public_key_t *public; |
d2fc9b09 | 924 | chunk_t msg; |
400df4ca | 925 | |
d2fc9b09 PK |
926 | public = tls_find_public_key(this->peer_auth); |
927 | if (!public) | |
400df4ca | 928 | { |
3c19b346 | 929 | DBG1(DBG_TLS, "no trusted certificate found for '%Y' to verify TLS peer", |
400df4ca | 930 | this->peer); |
d2fc9b09 PK |
931 | this->alert->add(this->alert, TLS_FATAL, TLS_CERTIFICATE_UNKNOWN); |
932 | return NEED_MORE; | |
1db6bf2f | 933 | } |
d2fc9b09 PK |
934 | |
935 | msg = reader->peek(reader); | |
936 | if (!this->crypto->verify_handshake(this->crypto, public, reader)) | |
1db6bf2f | 937 | { |
d2fc9b09 PK |
938 | public->destroy(public); |
939 | DBG1(DBG_TLS, "signature verification failed"); | |
940 | this->alert->add(this->alert, TLS_FATAL, TLS_DECRYPT_ERROR); | |
941 | return NEED_MORE; | |
400df4ca | 942 | } |
d2fc9b09 PK |
943 | public->destroy(public); |
944 | this->state = STATE_CERT_VERIFY_RECEIVED; | |
945 | this->crypto->append_handshake(this->crypto, TLS_CERTIFICATE_VERIFY, msg); | |
400df4ca MW |
946 | return NEED_MORE; |
947 | } | |
948 | ||
949 | /** | |
950 | * Process finished message | |
951 | */ | |
952 | static status_t process_finished(private_tls_server_t *this, | |
7e432eff | 953 | bio_reader_t *reader) |
400df4ca | 954 | { |
7fbe2e27 PK |
955 | chunk_t received, verify_data; |
956 | u_char buf[12]; | |
400df4ca | 957 | |
7fbe2e27 | 958 | if (this->tls->get_version_max(this->tls) < TLS_1_3) |
400df4ca | 959 | { |
7fbe2e27 PK |
960 | if (!reader->read_data(reader, sizeof(buf), &received)) |
961 | { | |
962 | DBG1(DBG_TLS, "received client finished too short"); | |
963 | this->alert->add(this->alert, TLS_FATAL, TLS_DECODE_ERROR); | |
964 | return NEED_MORE; | |
965 | } | |
966 | if (!this->crypto->calculate_finished_legacy(this->crypto, | |
967 | "client finished", buf)) | |
968 | { | |
969 | DBG1(DBG_TLS, "calculating client finished failed"); | |
970 | this->alert->add(this->alert, TLS_FATAL, TLS_INTERNAL_ERROR); | |
971 | return NEED_MORE; | |
972 | } | |
973 | verify_data = chunk_from_thing(buf); | |
400df4ca | 974 | } |
7fbe2e27 | 975 | else |
400df4ca | 976 | { |
7fbe2e27 PK |
977 | received = reader->peek(reader); |
978 | if (!this->crypto->calculate_finished(this->crypto, FALSE, &verify_data)) | |
979 | { | |
980 | DBG1(DBG_TLS, "calculating client finished failed"); | |
981 | this->alert->add(this->alert, TLS_FATAL, TLS_INTERNAL_ERROR); | |
982 | return NEED_MORE; | |
983 | } | |
7fbe2e27 | 984 | this->crypto->change_cipher(this->crypto, TRUE); |
400df4ca | 985 | } |
7fbe2e27 PK |
986 | |
987 | if (!chunk_equals_const(received, verify_data)) | |
400df4ca | 988 | { |
3c19b346 | 989 | DBG1(DBG_TLS, "received client finished invalid"); |
e6f3ef13 MW |
990 | this->alert->add(this->alert, TLS_FATAL, TLS_DECRYPT_ERROR); |
991 | return NEED_MORE; | |
400df4ca MW |
992 | } |
993 | ||
7fbe2e27 PK |
994 | if (verify_data.ptr != buf) |
995 | { | |
996 | chunk_free(&verify_data); | |
997 | } | |
998 | ||
400df4ca MW |
999 | this->crypto->append_handshake(this->crypto, TLS_FINISHED, received); |
1000 | this->state = STATE_FINISHED_RECEIVED; | |
1001 | return NEED_MORE; | |
1002 | } | |
4c0c2283 | 1003 | |
ab70f68c PK |
1004 | /** |
1005 | * Process KeyUpdate message | |
1006 | */ | |
1007 | static status_t process_key_update(private_tls_server_t *this, | |
1008 | bio_reader_t *reader) | |
1009 | { | |
1010 | uint8_t update_requested; | |
1011 | ||
1012 | if (!reader->read_uint8(reader, &update_requested) || | |
1013 | update_requested > 1) | |
1014 | { | |
1015 | DBG1(DBG_TLS, "received invalid KeyUpdate"); | |
1016 | this->alert->add(this->alert, TLS_FATAL, TLS_DECODE_ERROR); | |
1017 | return NEED_MORE; | |
1018 | } | |
1019 | ||
1020 | if (!this->crypto->update_app_keys(this->crypto, TRUE)) | |
1021 | { | |
1022 | this->alert->add(this->alert, TLS_FATAL, TLS_INTERNAL_ERROR); | |
1023 | return NEED_MORE; | |
1024 | } | |
1025 | this->crypto->change_cipher(this->crypto, TRUE); | |
1026 | ||
1027 | if (update_requested) | |
1028 | { | |
1029 | DBG1(DBG_TLS, "client requested KeyUpdate"); | |
1030 | this->state = STATE_KEY_UPDATE_REQUESTED; | |
1031 | } | |
1032 | return NEED_MORE; | |
1033 | } | |
1034 | ||
4c0c2283 | 1035 | METHOD(tls_handshake_t, process, status_t, |
7e432eff | 1036 | private_tls_server_t *this, tls_handshake_type_t type, bio_reader_t *reader) |
4c0c2283 | 1037 | { |
400df4ca MW |
1038 | tls_handshake_type_t expected; |
1039 | ||
7fbe2e27 | 1040 | if (this->tls->get_version_max(this->tls) < TLS_1_3) |
400df4ca | 1041 | { |
7fbe2e27 PK |
1042 | switch (this->state) |
1043 | { | |
1044 | case STATE_INIT: | |
1045 | if (type == TLS_CLIENT_HELLO) | |
1046 | { | |
1047 | return process_client_hello(this, reader); | |
1048 | } | |
1049 | expected = TLS_CLIENT_HELLO; | |
b51ac45c | 1050 | break; |
7fbe2e27 PK |
1051 | case STATE_HELLO_DONE: |
1052 | if (type == TLS_CERTIFICATE) | |
1053 | { | |
1054 | return process_certificate(this, reader); | |
1055 | } | |
1056 | if (this->peer) | |
1057 | { | |
1058 | expected = TLS_CERTIFICATE; | |
1059 | break; | |
1060 | } | |
1061 | /* otherwise fall through to next state */ | |
1062 | case STATE_CERT_RECEIVED: | |
1063 | if (type == TLS_CLIENT_KEY_EXCHANGE) | |
1064 | { | |
1065 | return process_key_exchange(this, reader); | |
1066 | } | |
1067 | expected = TLS_CLIENT_KEY_EXCHANGE; | |
b51ac45c | 1068 | break; |
7fbe2e27 PK |
1069 | case STATE_KEY_EXCHANGE_RECEIVED: |
1070 | if (type == TLS_CERTIFICATE_VERIFY) | |
1071 | { | |
1072 | return process_cert_verify(this, reader); | |
1073 | } | |
1074 | if (this->peer) | |
1075 | { | |
1076 | expected = TLS_CERTIFICATE_VERIFY; | |
1077 | break; | |
1078 | } | |
1079 | return INVALID_STATE; | |
1080 | case STATE_CIPHERSPEC_CHANGED_IN: | |
1081 | if (type == TLS_FINISHED) | |
1082 | { | |
1083 | return process_finished(this, reader); | |
1084 | } | |
1085 | expected = TLS_FINISHED; | |
1086 | break; | |
1087 | default: | |
1088 | DBG1(DBG_TLS, "TLS %N not expected in current state", | |
1089 | tls_handshake_type_names, type); | |
1090 | this->alert->add(this->alert, TLS_FATAL, TLS_UNEXPECTED_MESSAGE); | |
1091 | return NEED_MORE; | |
1092 | } | |
1093 | } | |
1094 | else | |
1095 | { | |
1096 | switch (this->state) | |
1097 | { | |
1098 | case STATE_INIT: | |
1099 | if (type == TLS_CLIENT_HELLO) | |
1100 | { | |
1101 | return process_client_hello(this, reader); | |
1102 | } | |
1103 | expected = TLS_CLIENT_HELLO; | |
1104 | break; | |
1105 | case STATE_CIPHERSPEC_CHANGED_IN: | |
1106 | case STATE_FINISHED_SENT: | |
d2fc9b09 PK |
1107 | case STATE_FINISHED_SENT_KEY_SWITCHED: |
1108 | if (type == TLS_CERTIFICATE) | |
1109 | { | |
1110 | return process_certificate(this, reader); | |
1111 | } | |
1112 | if (this->peer) | |
1113 | { | |
1114 | expected = TLS_CERTIFICATE; | |
1115 | break; | |
1116 | } | |
1117 | /* otherwise fall through to next state */ | |
1118 | case STATE_CERT_RECEIVED: | |
1119 | if (type == TLS_CERTIFICATE_VERIFY) | |
1120 | { | |
1121 | return process_cert_verify(this, reader); | |
1122 | } | |
1123 | if (this->peer) | |
1124 | { | |
1125 | expected = TLS_CERTIFICATE_VERIFY; | |
1126 | break; | |
1127 | } | |
1128 | /* otherwise fall through to next state */ | |
1129 | case STATE_CERT_VERIFY_RECEIVED: | |
7fbe2e27 PK |
1130 | if (type == TLS_FINISHED) |
1131 | { | |
1132 | return process_finished(this, reader); | |
1133 | } | |
1134 | return NEED_MORE; | |
1135 | case STATE_FINISHED_RECEIVED: | |
ab70f68c PK |
1136 | if (type == TLS_KEY_UPDATE) |
1137 | { | |
1138 | return process_key_update(this, reader); | |
1139 | } | |
7fbe2e27 PK |
1140 | return INVALID_STATE; |
1141 | default: | |
1142 | DBG1(DBG_TLS, "TLS %N not expected in current state", | |
1143 | tls_handshake_type_names, type); | |
1144 | this->alert->add(this->alert, TLS_FATAL, TLS_UNEXPECTED_MESSAGE); | |
1145 | return NEED_MORE; | |
1146 | } | |
400df4ca | 1147 | } |
3c19b346 | 1148 | DBG1(DBG_TLS, "TLS %N expected, but received %N", |
400df4ca | 1149 | tls_handshake_type_names, expected, tls_handshake_type_names, type); |
e6f3ef13 MW |
1150 | this->alert->add(this->alert, TLS_FATAL, TLS_UNEXPECTED_MESSAGE); |
1151 | return NEED_MORE; | |
400df4ca MW |
1152 | } |
1153 | ||
5c4cb40e PK |
1154 | /** |
1155 | * Write public key into key share extension | |
1156 | */ | |
066ac880 | 1157 | bool tls_write_key_share(bio_writer_t **key_share, diffie_hellman_t *dh) |
5c4cb40e PK |
1158 | { |
1159 | bio_writer_t *writer; | |
066ac880 | 1160 | tls_named_group_t curve; |
5c4cb40e PK |
1161 | chunk_t pub; |
1162 | ||
066ac880 PK |
1163 | if (!dh) |
1164 | { | |
1165 | return FALSE; | |
1166 | } | |
1167 | curve = tls_ec_group_to_curve(dh->get_dh_group(dh)); | |
1168 | if (!curve || !dh->get_my_public_value(dh, &pub)) | |
5c4cb40e PK |
1169 | { |
1170 | return FALSE; | |
1171 | } | |
1172 | *key_share = writer = bio_writer_create(pub.len + 7); | |
066ac880 PK |
1173 | writer->write_uint16(writer, curve); |
1174 | if (curve == TLS_CURVE25519 || | |
1175 | curve == TLS_CURVE448) | |
5c4cb40e PK |
1176 | { |
1177 | writer->write_data16(writer, pub); | |
1178 | } | |
1179 | else | |
1180 | { /* classic format (see RFC 8446, section 4.2.8.2) */ | |
1181 | writer->write_uint16(writer, pub.len + 1); | |
1182 | writer->write_uint8(writer, TLS_ANSI_UNCOMPRESSED); | |
1183 | writer->write_data(writer, pub); | |
1184 | } | |
1185 | free(pub.ptr); | |
1186 | return TRUE; | |
1187 | } | |
1188 | ||
400df4ca MW |
1189 | /** |
1190 | * Send ServerHello message | |
1191 | */ | |
1192 | static status_t send_server_hello(private_tls_server_t *this, | |
7e432eff | 1193 | tls_handshake_type_t *type, bio_writer_t *writer) |
400df4ca | 1194 | { |
5c4cb40e PK |
1195 | bio_writer_t *key_share, *extensions; |
1196 | tls_version_t version; | |
1197 | ||
1198 | version = this->tls->get_version_max(this->tls); | |
7fbe2e27 PK |
1199 | |
1200 | /* cap legacy version at TLS 1.2 for middlebox compatibility */ | |
1201 | writer->write_uint16(writer, min(TLS_1_2, version)); | |
c3e71324 PK |
1202 | |
1203 | if (this->requested_curve) | |
1204 | { | |
1205 | writer->write_data(writer, tls_hello_retry_request_magic); | |
1206 | } | |
1207 | else | |
1208 | { | |
1209 | writer->write_data(writer, chunk_from_thing(this->server_random)); | |
1210 | } | |
7ea87db0 | 1211 | |
6a5c86b7 MW |
1212 | /* session identifier if we have one */ |
1213 | writer->write_data8(writer, this->session); | |
7ea87db0 AS |
1214 | |
1215 | /* add selected TLS cipher suite */ | |
400df4ca | 1216 | writer->write_uint16(writer, this->suite); |
7ea87db0 | 1217 | |
400df4ca MW |
1218 | /* NULL compression only */ |
1219 | writer->write_uint8(writer, 0); | |
1220 | ||
7fbe2e27 PK |
1221 | if (version >= TLS_1_3) |
1222 | { | |
1223 | extensions = bio_writer_create(32); | |
1224 | ||
1225 | DBG2(DBG_TLS, "sending extension: %N", | |
1226 | tls_extension_names, TLS_EXT_SUPPORTED_VERSIONS); | |
1227 | extensions->write_uint16(extensions, TLS_EXT_SUPPORTED_VERSIONS); | |
1228 | extensions->write_uint16(extensions, 2); | |
1229 | extensions->write_uint16(extensions, version); | |
1230 | ||
5c4cb40e PK |
1231 | DBG2(DBG_TLS, "sending extension: %N", |
1232 | tls_extension_names, TLS_EXT_KEY_SHARE); | |
1233 | extensions->write_uint16(extensions, TLS_EXT_KEY_SHARE); | |
c3e71324 | 1234 | if (this->requested_curve) |
5c4cb40e | 1235 | { |
c3e71324 PK |
1236 | DBG1(DBG_TLS, "requesting key exchange with %N", |
1237 | tls_named_group_names, this->requested_curve); | |
1238 | extensions->write_uint16(extensions, 2); | |
1239 | extensions->write_uint16(extensions, this->requested_curve); | |
1240 | } | |
1241 | else | |
1242 | { | |
1243 | if (!tls_write_key_share(&key_share, this->dh)) | |
1244 | { | |
1245 | this->alert->add(this->alert, TLS_FATAL, TLS_INTERNAL_ERROR); | |
1246 | extensions->destroy(extensions); | |
1247 | return NEED_MORE; | |
1248 | } | |
1249 | extensions->write_data16(extensions, key_share->get_buf(key_share)); | |
1250 | key_share->destroy(key_share); | |
7fbe2e27 PK |
1251 | } |
1252 | ||
1253 | writer->write_data16(writer, extensions->get_buf(extensions)); | |
1254 | extensions->destroy(extensions); | |
1255 | } | |
1256 | ||
400df4ca | 1257 | *type = TLS_SERVER_HELLO; |
c3e71324 | 1258 | this->state = this->requested_curve ? STATE_INIT : STATE_HELLO_SENT; |
400df4ca MW |
1259 | this->crypto->append_handshake(this->crypto, *type, writer->get_buf(writer)); |
1260 | return NEED_MORE; | |
1261 | } | |
1262 | ||
7fbe2e27 PK |
1263 | /** |
1264 | * Send encrypted extensions message | |
1265 | */ | |
1266 | static status_t send_encrypted_extensions(private_tls_server_t *this, | |
1267 | tls_handshake_type_t *type, | |
1268 | bio_writer_t *writer) | |
1269 | { | |
1270 | chunk_t shared_secret = chunk_empty; | |
1271 | ||
1272 | if (!this->dh->get_shared_secret(this->dh, &shared_secret) || | |
1273 | !this->crypto->derive_handshake_keys(this->crypto, shared_secret)) | |
1274 | { | |
1275 | DBG1(DBG_TLS, "DH key derivation failed"); | |
1276 | this->alert->add(this->alert, TLS_FATAL, TLS_HANDSHAKE_FAILURE); | |
1277 | chunk_clear(&shared_secret); | |
1278 | return NEED_MORE; | |
1279 | } | |
1280 | chunk_clear(&shared_secret); | |
1281 | ||
1282 | this->crypto->change_cipher(this->crypto, TRUE); | |
1283 | this->crypto->change_cipher(this->crypto, FALSE); | |
1284 | ||
1285 | /* currently no extensions are supported */ | |
1286 | writer->write_uint16(writer, 0); | |
1287 | ||
1288 | *type = TLS_ENCRYPTED_EXTENSIONS; | |
1289 | this->state = STATE_ENCRYPTED_EXTENSIONS_SENT; | |
1290 | this->crypto->append_handshake(this->crypto, *type, writer->get_buf(writer)); | |
1291 | return NEED_MORE; | |
1292 | } | |
1293 | ||
400df4ca MW |
1294 | /** |
1295 | * Send Certificate | |
1296 | */ | |
1297 | static status_t send_certificate(private_tls_server_t *this, | |
7e432eff | 1298 | tls_handshake_type_t *type, bio_writer_t *writer) |
400df4ca MW |
1299 | { |
1300 | enumerator_t *enumerator; | |
1301 | certificate_t *cert; | |
1302 | auth_rule_t rule; | |
7e432eff | 1303 | bio_writer_t *certs; |
400df4ca MW |
1304 | chunk_t data; |
1305 | ||
7fbe2e27 PK |
1306 | /* certificate request context as described in RFC 8446, section 4.4.2 */ |
1307 | if (this->tls->get_version_max(this->tls) > TLS_1_2) | |
1308 | { | |
1309 | writer->write_uint8(writer, 0); | |
1310 | } | |
1311 | ||
400df4ca | 1312 | /* generate certificate payload */ |
7e432eff | 1313 | certs = bio_writer_create(256); |
400df4ca MW |
1314 | cert = this->server_auth->get(this->server_auth, AUTH_RULE_SUBJECT_CERT); |
1315 | if (cert) | |
1316 | { | |
0b71bc7a MW |
1317 | if (cert->get_encoding(cert, CERT_ASN1_DER, &data)) |
1318 | { | |
3c19b346 | 1319 | DBG1(DBG_TLS, "sending TLS server certificate '%Y'", |
0b71bc7a MW |
1320 | cert->get_subject(cert)); |
1321 | certs->write_data24(certs, data); | |
1322 | free(data.ptr); | |
1323 | } | |
7fbe2e27 PK |
1324 | /* extensions see RFC 8446, section 4.4.2 */ |
1325 | if (this->tls->get_version_max(this->tls) > TLS_1_2) | |
1326 | { | |
1327 | certs->write_uint16(certs, 0); | |
1328 | } | |
400df4ca MW |
1329 | } |
1330 | enumerator = this->server_auth->create_enumerator(this->server_auth); | |
1331 | while (enumerator->enumerate(enumerator, &rule, &cert)) | |
1332 | { | |
1333 | if (rule == AUTH_RULE_IM_CERT) | |
1334 | { | |
0b71bc7a MW |
1335 | if (cert->get_encoding(cert, CERT_ASN1_DER, &data)) |
1336 | { | |
3c19b346 | 1337 | DBG1(DBG_TLS, "sending TLS intermediate certificate '%Y'", |
0b71bc7a MW |
1338 | cert->get_subject(cert)); |
1339 | certs->write_data24(certs, data); | |
1340 | free(data.ptr); | |
1341 | } | |
400df4ca MW |
1342 | } |
1343 | } | |
1344 | enumerator->destroy(enumerator); | |
1345 | ||
1346 | writer->write_data24(writer, certs->get_buf(certs)); | |
1347 | certs->destroy(certs); | |
1348 | ||
1349 | *type = TLS_CERTIFICATE; | |
1350 | this->state = STATE_CERT_SENT; | |
1351 | this->crypto->append_handshake(this->crypto, *type, writer->get_buf(writer)); | |
1352 | return NEED_MORE; | |
1353 | } | |
1354 | ||
7fbe2e27 PK |
1355 | /** |
1356 | * Send Certificate Verify | |
1357 | */ | |
1358 | static status_t send_certificate_verify(private_tls_server_t *this, | |
1359 | tls_handshake_type_t *type, | |
1360 | bio_writer_t *writer) | |
1361 | { | |
1362 | if (!this->crypto->sign_handshake(this->crypto, this->private, writer, | |
1363 | this->hashsig)) | |
1364 | { | |
1365 | DBG1(DBG_TLS, "signature generation failed"); | |
1366 | this->alert->add(this->alert, TLS_FATAL, TLS_INTERNAL_ERROR); | |
1367 | return NEED_MORE; | |
1368 | } | |
1369 | ||
1370 | *type = TLS_CERTIFICATE_VERIFY; | |
1371 | this->state = STATE_CERT_VERIFY_SENT; | |
1372 | this->crypto->append_handshake(this->crypto, *type, writer->get_buf(writer)); | |
1373 | return NEED_MORE; | |
1374 | } | |
1375 | ||
d2fc9b09 PK |
1376 | /* |
1377 | * Write all available certificate authorities to output writer | |
dbb7c030 | 1378 | */ |
d2fc9b09 | 1379 | static void write_certificate_authorities(bio_writer_t *writer) |
dbb7c030 | 1380 | { |
d2fc9b09 | 1381 | bio_writer_t *authorities; |
d29a82a9 MW |
1382 | enumerator_t *enumerator; |
1383 | certificate_t *cert; | |
1384 | x509_t *x509; | |
1385 | identification_t *id; | |
dbb7c030 | 1386 | |
7e432eff | 1387 | authorities = bio_writer_create(64); |
d2fc9b09 PK |
1388 | enumerator = lib->credmgr->create_cert_enumerator(lib->credmgr, CERT_X509, |
1389 | KEY_RSA, NULL, TRUE); | |
400df4ca MW |
1390 | while (enumerator->enumerate(enumerator, &cert)) |
1391 | { | |
714d0bfd MW |
1392 | x509 = (x509_t*)cert; |
1393 | if (x509->get_flags(x509) & X509_CA) | |
1394 | { | |
1395 | id = cert->get_subject(cert); | |
3c19b346 | 1396 | DBG1(DBG_TLS, "sending TLS cert request for '%Y'", id); |
714d0bfd MW |
1397 | authorities->write_data16(authorities, id->get_encoding(id)); |
1398 | } | |
400df4ca MW |
1399 | } |
1400 | enumerator->destroy(enumerator); | |
1401 | writer->write_data16(writer, authorities->get_buf(authorities)); | |
1402 | authorities->destroy(authorities); | |
d2fc9b09 PK |
1403 | } |
1404 | ||
1405 | /** | |
1406 | * Send Certificate Request | |
1407 | */ | |
1408 | static status_t send_certificate_request(private_tls_server_t *this, | |
1409 | tls_handshake_type_t *type, | |
1410 | bio_writer_t *writer) | |
1411 | { | |
1412 | bio_writer_t *authorities, *supported, *extensions; | |
1413 | ||
1414 | if (this->tls->get_version_max(this->tls) < TLS_1_3) | |
1415 | { | |
1416 | supported = bio_writer_create(4); | |
1417 | /* we propose both RSA and ECDSA */ | |
1418 | supported->write_uint8(supported, TLS_RSA_SIGN); | |
1419 | supported->write_uint8(supported, TLS_ECDSA_SIGN); | |
1420 | writer->write_data8(writer, supported->get_buf(supported)); | |
1421 | supported->destroy(supported); | |
1422 | if (this->tls->get_version_max(this->tls) >= TLS_1_2) | |
1423 | { | |
1424 | this->crypto->get_signature_algorithms(this->crypto, writer, TRUE); | |
1425 | } | |
1426 | ||
a4a128bd SL |
1427 | if (this->send_certreq_authorities) |
1428 | { | |
1429 | write_certificate_authorities(writer); | |
1430 | } | |
1431 | else | |
1432 | { | |
1433 | writer->write_data16(writer, chunk_empty); | |
1434 | } | |
d2fc9b09 PK |
1435 | } |
1436 | else | |
1437 | { | |
1438 | /* certificate request context as described in RFC 8446, section 4.3.2 */ | |
1439 | writer->write_uint8(writer, 0); | |
1440 | ||
1441 | extensions = bio_writer_create(32); | |
a4a128bd SL |
1442 | |
1443 | if (this->send_certreq_authorities) | |
1444 | { | |
1445 | DBG2(DBG_TLS, "sending extension: %N", | |
1446 | tls_extension_names, TLS_EXT_CERTIFICATE_AUTHORITIES); | |
1447 | authorities = bio_writer_create(64); | |
1448 | write_certificate_authorities(authorities); | |
1449 | extensions->write_uint16(extensions, TLS_EXT_CERTIFICATE_AUTHORITIES); | |
1450 | extensions->write_data16(extensions, authorities->get_buf(authorities)); | |
1451 | authorities->destroy(authorities); | |
1452 | } | |
d2fc9b09 PK |
1453 | |
1454 | DBG2(DBG_TLS, "sending extension: %N", | |
1455 | tls_extension_names, TLS_EXT_SIGNATURE_ALGORITHMS); | |
1456 | extensions->write_uint16(extensions, TLS_EXT_SIGNATURE_ALGORITHMS); | |
1457 | supported = bio_writer_create(32); | |
1458 | this->crypto->get_signature_algorithms(this->crypto, supported, TRUE); | |
1459 | extensions->write_data16(extensions, supported->get_buf(supported)); | |
1460 | supported->destroy(supported); | |
1461 | writer->write_data16(writer, extensions->get_buf(extensions)); | |
1462 | extensions->destroy(extensions); | |
1463 | } | |
400df4ca MW |
1464 | |
1465 | *type = TLS_CERTIFICATE_REQUEST; | |
1466 | this->state = STATE_CERTREQ_SENT; | |
1467 | this->crypto->append_handshake(this->crypto, *type, writer->get_buf(writer)); | |
1468 | return NEED_MORE; | |
1469 | } | |
1470 | ||
37a59a8f | 1471 | /** |
3f7bb88b | 1472 | * Try to find a curve supported by both, client and server |
37a59a8f | 1473 | */ |
3f7bb88b | 1474 | static bool find_supported_curve(private_tls_server_t *this, |
7fbe2e27 | 1475 | tls_named_group_t *curve) |
37a59a8f | 1476 | { |
7a2b0266 | 1477 | tls_named_group_t current; |
3f7bb88b MW |
1478 | enumerator_t *enumerator; |
1479 | ||
1480 | enumerator = this->crypto->create_ec_enumerator(this->crypto); | |
1481 | while (enumerator->enumerate(enumerator, NULL, ¤t)) | |
1482 | { | |
1483 | if (peer_supports_curve(this, current)) | |
37a59a8f | 1484 | { |
3f7bb88b MW |
1485 | *curve = current; |
1486 | enumerator->destroy(enumerator); | |
37a59a8f MW |
1487 | return TRUE; |
1488 | } | |
1489 | } | |
3f7bb88b | 1490 | enumerator->destroy(enumerator); |
37a59a8f MW |
1491 | return FALSE; |
1492 | } | |
1493 | ||
f14358a9 MW |
1494 | /** |
1495 | * Send Server key Exchange | |
1496 | */ | |
1497 | static status_t send_server_key_exchange(private_tls_server_t *this, | |
7e432eff | 1498 | tls_handshake_type_t *type, bio_writer_t *writer, |
f14358a9 MW |
1499 | diffie_hellman_group_t group) |
1500 | { | |
141d7f7a | 1501 | diffie_hellman_params_t *params = NULL; |
7a2b0266 | 1502 | tls_named_group_t curve; |
f14358a9 MW |
1503 | chunk_t chunk; |
1504 | ||
f4c98ae6 | 1505 | if (diffie_hellman_group_is_ec(group)) |
141d7f7a | 1506 | { |
066ac880 | 1507 | curve = tls_ec_group_to_curve(group); |
3f7bb88b MW |
1508 | if (!curve || (!peer_supports_curve(this, curve) && |
1509 | !find_supported_curve(this, &curve))) | |
f4c98ae6 MW |
1510 | { |
1511 | DBG1(DBG_TLS, "no EC group supported by client and server"); | |
1512 | this->alert->add(this->alert, TLS_FATAL, TLS_HANDSHAKE_FAILURE); | |
1513 | return NEED_MORE; | |
1514 | } | |
7a2b0266 | 1515 | DBG2(DBG_TLS, "selected ECDH group %N", tls_named_group_names, curve); |
f4c98ae6 | 1516 | writer->write_uint8(writer, TLS_ECC_NAMED_CURVE); |
3f7bb88b | 1517 | writer->write_uint16(writer, curve); |
f4c98ae6 MW |
1518 | } |
1519 | else | |
1520 | { | |
1521 | params = diffie_hellman_get_params(group); | |
1522 | if (!params) | |
1523 | { | |
1524 | DBG1(DBG_TLS, "no parameters found for DH group %N", | |
1525 | diffie_hellman_group_names, group); | |
1526 | this->alert->add(this->alert, TLS_FATAL, TLS_INTERNAL_ERROR); | |
1527 | return NEED_MORE; | |
1528 | } | |
e4fd2bb4 | 1529 | DBG2(DBG_TLS, "selected DH group %N", diffie_hellman_group_names, group); |
f4c98ae6 MW |
1530 | writer->write_data16(writer, params->prime); |
1531 | writer->write_data16(writer, params->generator); | |
141d7f7a | 1532 | } |
37a59a8f MW |
1533 | this->dh = lib->crypto->create_dh(lib->crypto, group); |
1534 | if (!this->dh) | |
1535 | { | |
1536 | DBG1(DBG_TLS, "DH group %N not supported", | |
1537 | diffie_hellman_group_names, group); | |
1538 | this->alert->add(this->alert, TLS_FATAL, TLS_INTERNAL_ERROR); | |
1539 | return NEED_MORE; | |
1540 | } | |
42431690 MW |
1541 | if (!this->dh->get_my_public_value(this->dh, &chunk)) |
1542 | { | |
1543 | this->alert->add(this->alert, TLS_FATAL, TLS_INTERNAL_ERROR); | |
1544 | return NEED_MORE; | |
1545 | } | |
141d7f7a MW |
1546 | if (params) |
1547 | { | |
1548 | writer->write_data16(writer, chunk); | |
1549 | } | |
966a26ea TB |
1550 | else if (group != CURVE_25519 && |
1551 | group != CURVE_448) | |
e6cce7ff MW |
1552 | { /* ECP uses 8bit length header only, but a point format */ |
1553 | writer->write_uint8(writer, chunk.len + 1); | |
ec7d4e70 | 1554 | writer->write_uint8(writer, TLS_ANSI_UNCOMPRESSED); |
e6cce7ff | 1555 | writer->write_data(writer, chunk); |
141d7f7a | 1556 | } |
966a26ea TB |
1557 | else |
1558 | { /* ECPoint uses an 8-bit length header only */ | |
1559 | writer->write_data8(writer, chunk); | |
1560 | } | |
f14358a9 MW |
1561 | free(chunk.ptr); |
1562 | ||
1563 | chunk = chunk_cat("ccc", chunk_from_thing(this->client_random), | |
1564 | chunk_from_thing(this->server_random), writer->get_buf(writer)); | |
1565 | if (!this->private || !this->crypto->sign(this->crypto, this->private, | |
1566 | writer, chunk, this->hashsig)) | |
1567 | { | |
1568 | DBG1(DBG_TLS, "signing DH parameters failed"); | |
1569 | this->alert->add(this->alert, TLS_FATAL, TLS_INTERNAL_ERROR); | |
1570 | free(chunk.ptr); | |
1571 | return NEED_MORE; | |
1572 | } | |
1573 | free(chunk.ptr); | |
1574 | *type = TLS_SERVER_KEY_EXCHANGE; | |
1575 | this->state = STATE_KEY_EXCHANGE_SENT; | |
1576 | this->crypto->append_handshake(this->crypto, *type, writer->get_buf(writer)); | |
1577 | return NEED_MORE; | |
1578 | } | |
1579 | ||
400df4ca MW |
1580 | /** |
1581 | * Send Hello Done | |
1582 | */ | |
1583 | static status_t send_hello_done(private_tls_server_t *this, | |
7e432eff | 1584 | tls_handshake_type_t *type, bio_writer_t *writer) |
400df4ca MW |
1585 | { |
1586 | *type = TLS_SERVER_HELLO_DONE; | |
1587 | this->state = STATE_HELLO_DONE; | |
1588 | this->crypto->append_handshake(this->crypto, *type, writer->get_buf(writer)); | |
1589 | return NEED_MORE; | |
1590 | } | |
1591 | ||
1592 | /** | |
1593 | * Send Finished | |
1594 | */ | |
1595 | static status_t send_finished(private_tls_server_t *this, | |
7e432eff | 1596 | tls_handshake_type_t *type, bio_writer_t *writer) |
400df4ca | 1597 | { |
7fbe2e27 | 1598 | if (this->tls->get_version_max(this->tls) < TLS_1_3) |
400df4ca | 1599 | { |
7fbe2e27 PK |
1600 | char buf[12]; |
1601 | ||
1602 | if (!this->crypto->calculate_finished_legacy(this->crypto, | |
1603 | "server finished", buf)) | |
1604 | { | |
1605 | DBG1(DBG_TLS, "calculating server finished data failed"); | |
1606 | this->alert->add(this->alert, TLS_FATAL, TLS_INTERNAL_ERROR); | |
1607 | return FAILED; | |
1608 | } | |
1609 | ||
1610 | writer->write_data(writer, chunk_from_thing(buf)); | |
400df4ca | 1611 | } |
7fbe2e27 PK |
1612 | else |
1613 | { | |
1614 | chunk_t verify_data; | |
1615 | ||
1616 | if (!this->crypto->calculate_finished(this->crypto, TRUE, &verify_data)) | |
1617 | { | |
1618 | DBG1(DBG_TLS, "calculating server finished data failed"); | |
1619 | this->alert->add(this->alert, TLS_FATAL, TLS_INTERNAL_ERROR); | |
1620 | return NEED_MORE; | |
1621 | } | |
400df4ca | 1622 | |
7fbe2e27 PK |
1623 | writer->write_data(writer, verify_data); |
1624 | chunk_free(&verify_data); | |
1625 | } | |
400df4ca MW |
1626 | |
1627 | *type = TLS_FINISHED; | |
1628 | this->state = STATE_FINISHED_SENT; | |
6a5c86b7 MW |
1629 | this->crypto->append_handshake(this->crypto, *type, writer->get_buf(writer)); |
1630 | ||
4c0c2283 MW |
1631 | return NEED_MORE; |
1632 | } | |
1633 | ||
ab70f68c PK |
1634 | /** |
1635 | * Send KeyUpdate message | |
1636 | */ | |
1637 | static status_t send_key_update(private_tls_server_t *this, | |
1638 | tls_handshake_type_t *type, bio_writer_t *writer) | |
1639 | { | |
1640 | *type = TLS_KEY_UPDATE; | |
1641 | ||
1642 | /* we currently only send this as reply, so we never request an update */ | |
1643 | writer->write_uint8(writer, 0); | |
1644 | ||
1645 | this->state = STATE_KEY_UPDATE_SENT; | |
1646 | return NEED_MORE; | |
1647 | } | |
1648 | ||
4c0c2283 | 1649 | METHOD(tls_handshake_t, build, status_t, |
7e432eff | 1650 | private_tls_server_t *this, tls_handshake_type_t *type, bio_writer_t *writer) |
4c0c2283 | 1651 | { |
f14358a9 MW |
1652 | diffie_hellman_group_t group; |
1653 | ||
7fbe2e27 | 1654 | if (this->tls->get_version_max(this->tls) < TLS_1_3) |
400df4ca | 1655 | { |
7fbe2e27 PK |
1656 | switch (this->state) |
1657 | { | |
1658 | case STATE_HELLO_RECEIVED: | |
1659 | return send_server_hello(this, type, writer); | |
1660 | case STATE_HELLO_SENT: | |
1661 | return send_certificate(this, type, writer); | |
1662 | case STATE_CERT_SENT: | |
1663 | group = this->crypto->get_dh_group(this->crypto); | |
1664 | if (group) | |
1665 | { | |
1666 | return send_server_key_exchange(this, type, writer, group); | |
1667 | } | |
1668 | /* otherwise fall through to next state */ | |
1669 | case STATE_KEY_EXCHANGE_SENT: | |
4bba89ff PK |
1670 | if (this->peer) |
1671 | { | |
1672 | return send_certificate_request(this, type, writer); | |
1673 | } | |
1674 | /* otherwise fall through to next state */ | |
7fbe2e27 PK |
1675 | case STATE_CERTREQ_SENT: |
1676 | return send_hello_done(this, type, writer); | |
1677 | case STATE_CIPHERSPEC_CHANGED_OUT: | |
1678 | return send_finished(this, type, writer); | |
1679 | case STATE_FINISHED_SENT: | |
1680 | return INVALID_STATE; | |
1681 | default: | |
1682 | return INVALID_STATE; | |
1683 | } | |
1684 | } | |
1685 | else | |
1686 | { | |
1687 | switch (this->state) | |
1688 | { | |
1689 | case STATE_HELLO_RECEIVED: | |
1690 | return send_server_hello(this, type, writer); | |
1691 | case STATE_HELLO_SENT: | |
1692 | case STATE_CIPHERSPEC_CHANGED_OUT: | |
1693 | return send_encrypted_extensions(this, type, writer); | |
1694 | case STATE_ENCRYPTED_EXTENSIONS_SENT: | |
d2fc9b09 PK |
1695 | if (this->peer) |
1696 | { | |
1697 | return send_certificate_request(this, type, writer); | |
1698 | } | |
1699 | /* otherwise fall through to next state */ | |
1700 | case STATE_CERTREQ_SENT: | |
7fbe2e27 PK |
1701 | return send_certificate(this, type, writer); |
1702 | case STATE_CERT_SENT: | |
1703 | return send_certificate_verify(this, type, writer); | |
1704 | case STATE_CERT_VERIFY_SENT: | |
1705 | return send_finished(this, type, writer); | |
1706 | case STATE_FINISHED_SENT: | |
d2fc9b09 PK |
1707 | if (!this->crypto->derive_app_keys(this->crypto)) |
1708 | { | |
1709 | this->alert->add(this->alert, TLS_FATAL, TLS_INTERNAL_ERROR); | |
1710 | return NEED_MORE; | |
1711 | } | |
1712 | /* inbound key switches after process client finished message */ | |
1713 | this->crypto->change_cipher(this->crypto, FALSE); | |
1714 | this->state = STATE_FINISHED_SENT_KEY_SWITCHED; | |
7fbe2e27 | 1715 | return INVALID_STATE; |
ab70f68c PK |
1716 | case STATE_KEY_UPDATE_REQUESTED: |
1717 | return send_key_update(this, type, writer); | |
1718 | case STATE_KEY_UPDATE_SENT: | |
1719 | if (!this->crypto->update_app_keys(this->crypto, FALSE)) | |
1720 | { | |
1721 | this->alert->add(this->alert, TLS_FATAL, TLS_INTERNAL_ERROR); | |
1722 | return NEED_MORE; | |
1723 | } | |
1724 | this->crypto->change_cipher(this->crypto, FALSE); | |
1725 | this->state = STATE_FINISHED_RECEIVED; | |
7fbe2e27 PK |
1726 | default: |
1727 | return INVALID_STATE; | |
1728 | } | |
400df4ca | 1729 | } |
4c0c2283 MW |
1730 | } |
1731 | ||
3ddd164e | 1732 | METHOD(tls_handshake_t, cipherspec_changed, bool, |
4caa3806 | 1733 | private_tls_server_t *this, bool inbound) |
3ddd164e | 1734 | { |
7fbe2e27 | 1735 | if (this->tls->get_version_max(this->tls) < TLS_1_3) |
400df4ca | 1736 | { |
7fbe2e27 | 1737 | if (inbound) |
6a5c86b7 | 1738 | { |
7fbe2e27 PK |
1739 | if (this->resume) |
1740 | { | |
1741 | return this->state == STATE_FINISHED_SENT; | |
1742 | } | |
1743 | if (this->peer) | |
1744 | { | |
1745 | return this->state == STATE_CERT_VERIFY_RECEIVED; | |
1746 | } | |
1747 | return this->state == STATE_KEY_EXCHANGE_RECEIVED; | |
6a5c86b7 | 1748 | } |
7fbe2e27 | 1749 | else |
4caa3806 | 1750 | { |
7fbe2e27 PK |
1751 | if (this->resume) |
1752 | { | |
1753 | return this->state == STATE_HELLO_SENT; | |
1754 | } | |
1755 | return this->state == STATE_FINISHED_RECEIVED; | |
4caa3806 | 1756 | } |
7fbe2e27 | 1757 | return FALSE; |
4caa3806 MW |
1758 | } |
1759 | else | |
1760 | { | |
7fbe2e27 | 1761 | if (inbound) |
c3e71324 | 1762 | { /* accept ChangeCipherSpec after ServerFinish or HelloRetryRequest */ |
d2fc9b09 PK |
1763 | return this->state == STATE_FINISHED_SENT || |
1764 | this->state == STATE_FINISHED_SENT_KEY_SWITCHED || | |
1765 | retrying(this); | |
7fbe2e27 PK |
1766 | } |
1767 | else | |
6a5c86b7 MW |
1768 | { |
1769 | return this->state == STATE_HELLO_SENT; | |
1770 | } | |
400df4ca | 1771 | } |
3ddd164e MW |
1772 | } |
1773 | ||
4caa3806 MW |
1774 | METHOD(tls_handshake_t, change_cipherspec, void, |
1775 | private_tls_server_t *this, bool inbound) | |
3ddd164e | 1776 | { |
7fbe2e27 PK |
1777 | if (this->tls->get_version_max(this->tls) < TLS_1_3) |
1778 | { | |
1779 | this->crypto->change_cipher(this->crypto, inbound); | |
1780 | } | |
1781 | ||
c3e71324 PK |
1782 | if (retrying(this)) |
1783 | { /* client might send a ChangeCipherSpec after a HelloRetryRequest and | |
1784 | * before a new ClientHello which should not cause any state changes */ | |
1785 | return; | |
1786 | } | |
1787 | ||
4caa3806 | 1788 | if (inbound) |
400df4ca | 1789 | { |
400df4ca | 1790 | this->state = STATE_CIPHERSPEC_CHANGED_IN; |
400df4ca | 1791 | } |
4caa3806 MW |
1792 | else |
1793 | { | |
1794 | this->state = STATE_CIPHERSPEC_CHANGED_OUT; | |
1795 | } | |
3ddd164e MW |
1796 | } |
1797 | ||
1327839d AS |
1798 | METHOD(tls_handshake_t, finished, bool, |
1799 | private_tls_server_t *this) | |
1800 | { | |
7fbe2e27 PK |
1801 | if (this->tls->get_version_max(this->tls) < TLS_1_3) |
1802 | { | |
1803 | if (this->resume) | |
1804 | { | |
1805 | return this->state == STATE_FINISHED_RECEIVED; | |
1806 | } | |
1807 | return this->state == STATE_FINISHED_SENT; | |
1808 | } | |
1809 | else | |
6a5c86b7 MW |
1810 | { |
1811 | return this->state == STATE_FINISHED_RECEIVED; | |
1812 | } | |
1327839d AS |
1813 | } |
1814 | ||
2de481e3 MW |
1815 | METHOD(tls_handshake_t, get_peer_id, identification_t*, |
1816 | private_tls_server_t *this) | |
1817 | { | |
1818 | return this->peer; | |
1819 | } | |
1820 | ||
1821 | METHOD(tls_handshake_t, get_server_id, identification_t*, | |
1822 | private_tls_server_t *this) | |
1823 | { | |
1824 | return this->server; | |
1825 | } | |
1826 | ||
666c5523 MW |
1827 | METHOD(tls_handshake_t, get_auth, auth_cfg_t*, |
1828 | private_tls_server_t *this) | |
1829 | { | |
1830 | return this->peer_auth; | |
1831 | } | |
1832 | ||
4c0c2283 MW |
1833 | METHOD(tls_handshake_t, destroy, void, |
1834 | private_tls_server_t *this) | |
1835 | { | |
400df4ca | 1836 | DESTROY_IF(this->private); |
f14358a9 | 1837 | DESTROY_IF(this->dh); |
2de481e3 MW |
1838 | DESTROY_IF(this->peer); |
1839 | this->server->destroy(this->server); | |
400df4ca MW |
1840 | this->peer_auth->destroy(this->peer_auth); |
1841 | this->server_auth->destroy(this->server_auth); | |
06109c47 | 1842 | free(this->hashsig.ptr); |
37a59a8f | 1843 | free(this->curves.ptr); |
6a5c86b7 | 1844 | free(this->session.ptr); |
4c0c2283 MW |
1845 | free(this); |
1846 | } | |
1847 | ||
1848 | /** | |
1849 | * See header | |
1850 | */ | |
e6f3ef13 MW |
1851 | tls_server_t *tls_server_create(tls_t *tls, |
1852 | tls_crypto_t *crypto, tls_alert_t *alert, | |
1853 | identification_t *server, identification_t *peer) | |
4c0c2283 MW |
1854 | { |
1855 | private_tls_server_t *this; | |
1856 | ||
1857 | INIT(this, | |
ba31fe1f MW |
1858 | .public = { |
1859 | .handshake = { | |
1860 | .process = _process, | |
1861 | .build = _build, | |
1862 | .cipherspec_changed = _cipherspec_changed, | |
1863 | .change_cipherspec = _change_cipherspec, | |
1864 | .finished = _finished, | |
2de481e3 MW |
1865 | .get_peer_id = _get_peer_id, |
1866 | .get_server_id = _get_server_id, | |
666c5523 | 1867 | .get_auth = _get_auth, |
ba31fe1f MW |
1868 | .destroy = _destroy, |
1869 | }, | |
4c0c2283 | 1870 | }, |
3e962b08 | 1871 | .tls = tls, |
536dbc00 | 1872 | .crypto = crypto, |
e6f3ef13 | 1873 | .alert = alert, |
2de481e3 MW |
1874 | .server = server->clone(server), |
1875 | .peer = peer ? peer->clone(peer) : NULL, | |
400df4ca MW |
1876 | .state = STATE_INIT, |
1877 | .peer_auth = auth_cfg_create(), | |
1878 | .server_auth = auth_cfg_create(), | |
a4a128bd SL |
1879 | .send_certreq_authorities = lib->settings->get_bool(lib->settings, |
1880 | "%s.tls.send_certreq_authorities", | |
1881 | TRUE, lib->ns), | |
4c0c2283 MW |
1882 | ); |
1883 | ||
1884 | return &this->public; | |
1885 | } |