Delegate tls_t.get_{peer,server}_id to handshake layer
[strongswan.git] / src / libtls / tls.c
1 /*
2 * Copyright (C) 2010 Martin Willi
3 * Copyright (C) 2010 revosec AG
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 * for more details.
14 */
15
16 #include "tls.h"
17
18 #include <utils/debug.h>
19
20 #include "tls_protection.h"
21 #include "tls_compression.h"
22 #include "tls_fragmentation.h"
23 #include "tls_crypto.h"
24 #include "tls_server.h"
25 #include "tls_peer.h"
26
27 ENUM_BEGIN(tls_version_names, SSL_2_0, SSL_2_0,
28 "SSLv2");
29 ENUM_NEXT(tls_version_names, SSL_3_0, TLS_1_2, SSL_2_0,
30 "SSLv3",
31 "TLS 1.0",
32 "TLS 1.1",
33 "TLS 1.2");
34 ENUM_END(tls_version_names, TLS_1_2);
35
36 ENUM(tls_content_type_names, TLS_CHANGE_CIPHER_SPEC, TLS_APPLICATION_DATA,
37 "ChangeCipherSpec",
38 "Alert",
39 "Handshake",
40 "ApplicationData",
41 );
42
43 ENUM_BEGIN(tls_handshake_type_names, TLS_HELLO_REQUEST, TLS_SERVER_HELLO,
44 "HelloRequest",
45 "ClientHello",
46 "ServerHello");
47 ENUM_NEXT(tls_handshake_type_names,
48 TLS_CERTIFICATE, TLS_CLIENT_KEY_EXCHANGE, TLS_SERVER_HELLO,
49 "Certificate",
50 "ServerKeyExchange",
51 "CertificateRequest",
52 "ServerHelloDone",
53 "CertificateVerify",
54 "ClientKeyExchange");
55 ENUM_NEXT(tls_handshake_type_names,
56 TLS_FINISHED, TLS_FINISHED, TLS_CLIENT_KEY_EXCHANGE,
57 "Finished");
58 ENUM_END(tls_handshake_type_names, TLS_FINISHED);
59
60 ENUM_BEGIN(tls_extension_names, TLS_EXT_SERVER_NAME, TLS_EXT_STATUS_REQUEST,
61 "server name",
62 "max fragment length",
63 "client certificate url",
64 "trusted ca keys",
65 "truncated hmac",
66 "status request");
67 ENUM_NEXT(tls_extension_names,
68 TLS_EXT_ELLIPTIC_CURVES, TLS_EXT_EC_POINT_FORMATS,
69 TLS_EXT_STATUS_REQUEST,
70 "elliptic curves",
71 "ec point formats");
72 ENUM_NEXT(tls_extension_names,
73 TLS_EXT_SIGNATURE_ALGORITHMS, TLS_EXT_SIGNATURE_ALGORITHMS,
74 TLS_EXT_EC_POINT_FORMATS,
75 "signature algorithms");
76 ENUM_NEXT(tls_extension_names,
77 TLS_EXT_RENEGOTIATION_INFO, TLS_EXT_RENEGOTIATION_INFO,
78 TLS_EXT_SIGNATURE_ALGORITHMS,
79 "renegotiation info");
80 ENUM_END(tls_extension_names, TLS_EXT_RENEGOTIATION_INFO);
81
82 /**
83 * TLS record
84 */
85 typedef struct __attribute__((packed)) {
86 u_int8_t type;
87 u_int16_t version;
88 u_int16_t length;
89 char data[];
90 } tls_record_t;
91
92 typedef struct private_tls_t private_tls_t;
93
94 /**
95 * Private data of an tls_protection_t object.
96 */
97 struct private_tls_t {
98
99 /**
100 * Public tls_t interface.
101 */
102 tls_t public;
103
104 /**
105 * Role this TLS stack acts as.
106 */
107 bool is_server;
108
109 /**
110 * Negotiated TLS version
111 */
112 tls_version_t version;
113
114 /**
115 * TLS stack purpose, as given to constructor
116 */
117 tls_purpose_t purpose;
118
119 /**
120 * TLS record protection layer
121 */
122 tls_protection_t *protection;
123
124 /**
125 * TLS record compression layer
126 */
127 tls_compression_t *compression;
128
129 /**
130 * TLS record fragmentation layer
131 */
132 tls_fragmentation_t *fragmentation;
133
134 /**
135 * TLS alert handler
136 */
137 tls_alert_t *alert;
138
139 /**
140 * TLS crypto helper context
141 */
142 tls_crypto_t *crypto;
143
144 /**
145 * TLS handshake protocol handler
146 */
147 tls_handshake_t *handshake;
148
149 /**
150 * TLS application data handler
151 */
152 tls_application_t *application;
153
154 /**
155 * Allocated input buffer
156 */
157 chunk_t input;
158
159 /**
160 * Number of bytes read in input buffer
161 */
162 size_t inpos;
163
164 /**
165 * Allocated output buffer
166 */
167 chunk_t output;
168
169 /**
170 * Number of bytes processed from output buffer
171 */
172 size_t outpos;
173
174 /**
175 * Partial TLS record header received
176 */
177 tls_record_t head;
178
179 /**
180 * Position in partially received record header
181 */
182 size_t headpos;
183 };
184
185 /**
186 * Described in header.
187 */
188 void libtls_init(void)
189 {
190 /* empty */
191 }
192
193 METHOD(tls_t, process, status_t,
194 private_tls_t *this, void *buf, size_t buflen)
195 {
196 tls_record_t *record;
197 status_t status;
198 u_int len;
199
200 if (this->headpos)
201 { /* have a partial TLS record header, try to complete it */
202 len = min(buflen, sizeof(this->head) - this->headpos);
203 memcpy(((char*)&this->head) + this->headpos, buf, len);
204 this->headpos += len;
205 buflen -= len;
206 buf += len;
207 if (this->headpos == sizeof(this->head))
208 { /* header complete, allocate space with new header */
209 len = untoh16(&this->head.length);
210 this->input = chunk_alloc(len + sizeof(tls_record_t));
211 memcpy(this->input.ptr, &this->head, sizeof(this->head));
212 this->inpos = sizeof(this->head);
213 this->headpos = 0;
214 }
215 }
216
217 while (buflen)
218 {
219 if (this->input.len == 0)
220 {
221 if (buflen < sizeof(tls_record_t))
222 {
223 DBG2(DBG_TLS, "received incomplete TLS record header");
224 memcpy(&this->head, buf, buflen);
225 this->headpos = buflen;
226 break;
227 }
228 while (TRUE)
229 {
230 /* try to process records inline */
231 record = buf;
232 len = untoh16(&record->length);
233
234 if (len + sizeof(tls_record_t) > buflen)
235 { /* not a full record, read to buffer */
236 this->input = chunk_alloc(len + sizeof(tls_record_t));
237 this->inpos = 0;
238 break;
239 }
240 DBG2(DBG_TLS, "processing TLS %N record (%d bytes)",
241 tls_content_type_names, record->type, len);
242 status = this->protection->process(this->protection,
243 record->type, chunk_create(record->data, len));
244 if (status != NEED_MORE)
245 {
246 return status;
247 }
248 buf += len + sizeof(tls_record_t);
249 buflen -= len + sizeof(tls_record_t);
250 if (buflen == 0)
251 {
252 return NEED_MORE;
253 }
254 }
255 }
256 len = min(buflen, this->input.len - this->inpos);
257 memcpy(this->input.ptr + this->inpos, buf, len);
258 buf += len;
259 buflen -= len;
260 this->inpos += len;
261 DBG2(DBG_TLS, "buffering %d bytes, %d bytes of %d byte TLS record received",
262 len, this->inpos, this->input.len);
263 if (this->input.len == this->inpos)
264 {
265 record = (tls_record_t*)this->input.ptr;
266 len = untoh16(&record->length);
267
268 DBG2(DBG_TLS, "processing buffered TLS %N record (%d bytes)",
269 tls_content_type_names, record->type, len);
270 status = this->protection->process(this->protection,
271 record->type, chunk_create(record->data, len));
272 chunk_free(&this->input);
273 this->inpos = 0;
274 if (status != NEED_MORE)
275 {
276 return status;
277 }
278 }
279 }
280 return NEED_MORE;
281 }
282
283 METHOD(tls_t, build, status_t,
284 private_tls_t *this, void *buf, size_t *buflen, size_t *msglen)
285 {
286 tls_content_type_t type;
287 tls_record_t record;
288 status_t status;
289 chunk_t data;
290 size_t len;
291
292 len = *buflen;
293 if (this->output.len == 0)
294 {
295 /* query upper layers for new records, as many as we can get */
296 while (TRUE)
297 {
298 status = this->protection->build(this->protection, &type, &data);
299 switch (status)
300 {
301 case NEED_MORE:
302 record.type = type;
303 htoun16(&record.version, this->version);
304 htoun16(&record.length, data.len);
305 this->output = chunk_cat("mcm", this->output,
306 chunk_from_thing(record), data);
307 DBG2(DBG_TLS, "sending TLS %N record (%d bytes)",
308 tls_content_type_names, type, data.len);
309 continue;
310 case INVALID_STATE:
311 if (this->output.len == 0)
312 {
313 return INVALID_STATE;
314 }
315 break;
316 default:
317 return status;
318 }
319 break;
320 }
321 if (msglen)
322 {
323 *msglen = this->output.len;
324 }
325 }
326 else
327 {
328 if (msglen)
329 {
330 *msglen = 0;
331 }
332 }
333 len = min(len, this->output.len - this->outpos);
334 memcpy(buf, this->output.ptr + this->outpos, len);
335 this->outpos += len;
336 *buflen = len;
337 if (this->outpos == this->output.len)
338 {
339 chunk_free(&this->output);
340 this->outpos = 0;
341 return ALREADY_DONE;
342 }
343 return NEED_MORE;
344 }
345
346 METHOD(tls_t, is_server, bool,
347 private_tls_t *this)
348 {
349 return this->is_server;
350 }
351
352 METHOD(tls_t, get_server_id, identification_t*,
353 private_tls_t *this)
354 {
355 return this->handshake->get_server_id(this->handshake);
356 }
357
358 METHOD(tls_t, get_peer_id, identification_t*,
359 private_tls_t *this)
360 {
361 return this->handshake->get_peer_id(this->handshake);
362 }
363
364 METHOD(tls_t, get_version, tls_version_t,
365 private_tls_t *this)
366 {
367 return this->version;
368 }
369
370 METHOD(tls_t, set_version, bool,
371 private_tls_t *this, tls_version_t version)
372 {
373 if (version > this->version)
374 {
375 return FALSE;
376 }
377 switch (version)
378 {
379 case TLS_1_0:
380 case TLS_1_1:
381 case TLS_1_2:
382 this->version = version;
383 this->protection->set_version(this->protection, version);
384 return TRUE;
385 case SSL_2_0:
386 case SSL_3_0:
387 default:
388 return FALSE;
389 }
390 }
391
392 METHOD(tls_t, get_purpose, tls_purpose_t,
393 private_tls_t *this)
394 {
395 return this->purpose;
396 }
397
398 METHOD(tls_t, is_complete, bool,
399 private_tls_t *this)
400 {
401 if (this->handshake->finished(this->handshake))
402 {
403 if (!this->application)
404 {
405 return TRUE;
406 }
407 return this->fragmentation->application_finished(this->fragmentation);
408 }
409 return FALSE;
410 }
411
412 METHOD(tls_t, get_eap_msk, chunk_t,
413 private_tls_t *this)
414 {
415 return this->crypto->get_eap_msk(this->crypto);
416 }
417
418 METHOD(tls_t, destroy, void,
419 private_tls_t *this)
420 {
421 this->protection->destroy(this->protection);
422 this->compression->destroy(this->compression);
423 this->fragmentation->destroy(this->fragmentation);
424 this->crypto->destroy(this->crypto);
425 this->handshake->destroy(this->handshake);
426 DESTROY_IF(this->application);
427 this->alert->destroy(this->alert);
428
429 free(this->input.ptr);
430 free(this->output.ptr);
431
432 free(this);
433 }
434
435 /**
436 * See header
437 */
438 tls_t *tls_create(bool is_server, identification_t *server,
439 identification_t *peer, tls_purpose_t purpose,
440 tls_application_t *application, tls_cache_t *cache)
441 {
442 private_tls_t *this;
443
444 switch (purpose)
445 {
446 case TLS_PURPOSE_EAP_TLS:
447 case TLS_PURPOSE_EAP_TTLS:
448 case TLS_PURPOSE_EAP_PEAP:
449 case TLS_PURPOSE_GENERIC:
450 break;
451 default:
452 return NULL;
453 }
454
455 INIT(this,
456 .public = {
457 .process = _process,
458 .build = _build,
459 .is_server = _is_server,
460 .get_server_id = _get_server_id,
461 .get_peer_id = _get_peer_id,
462 .get_version = _get_version,
463 .set_version = _set_version,
464 .get_purpose = _get_purpose,
465 .is_complete = _is_complete,
466 .get_eap_msk = _get_eap_msk,
467 .destroy = _destroy,
468 },
469 .is_server = is_server,
470 .version = TLS_1_2,
471 .application = application,
472 .purpose = purpose,
473 );
474
475 this->crypto = tls_crypto_create(&this->public, cache);
476 this->alert = tls_alert_create();
477 if (is_server)
478 {
479 this->handshake = &tls_server_create(&this->public, this->crypto,
480 this->alert, server, peer)->handshake;
481 }
482 else
483 {
484 this->handshake = &tls_peer_create(&this->public, this->crypto,
485 this->alert, peer, server)->handshake;
486 }
487 this->fragmentation = tls_fragmentation_create(this->handshake, this->alert,
488 this->application);
489 this->compression = tls_compression_create(this->fragmentation, this->alert);
490 this->protection = tls_protection_create(this->compression, this->alert);
491 this->crypto->set_protection(this->crypto, this->protection);
492
493 return &this->public;
494 }