trap-manager: Wait for install to finish before uninstalling
[strongswan.git] / src / libtls / tls_protection.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_protection.h"
17
18 #include <utils/debug.h>
19
20 typedef struct private_tls_protection_t private_tls_protection_t;
21
22 /**
23 * Private data of an tls_protection_t object.
24 */
25 struct private_tls_protection_t {
26
27 /**
28 * Public tls_protection_t interface.
29 */
30 tls_protection_t public;
31
32 /**
33 * negotiated TLS version
34 */
35 tls_version_t version;
36
37 /**
38 * Upper layer, TLS record compression
39 */
40 tls_compression_t *compression;
41
42 /**
43 * TLS alert handler
44 */
45 tls_alert_t *alert;
46
47 /**
48 * Sequence number of incoming records
49 */
50 uint64_t seq_in;
51
52 /**
53 * Sequence number for outgoing records
54 */
55 uint64_t seq_out;
56
57 /**
58 * AEAD transform for inbound traffic
59 */
60 tls_aead_t *aead_in;
61
62 /**
63 * AEAD transform for outbound traffic
64 */
65 tls_aead_t *aead_out;
66 };
67
68 METHOD(tls_protection_t, process, status_t,
69 private_tls_protection_t *this, tls_content_type_t type, chunk_t data)
70 {
71 if (this->alert->fatal(this->alert))
72 { /* don't accept more input, fatal error occurred */
73 return NEED_MORE;
74 }
75
76 if (this->aead_in)
77 {
78 if (!this->aead_in->decrypt(this->aead_in, this->version,
79 type, this->seq_in, &data))
80 {
81 DBG1(DBG_TLS, "TLS record decryption failed");
82 this->alert->add(this->alert, TLS_FATAL, TLS_BAD_RECORD_MAC);
83 return NEED_MORE;
84 }
85 }
86
87 if (type == TLS_CHANGE_CIPHER_SPEC)
88 {
89 this->seq_in = 0;
90 }
91 else
92 {
93 this->seq_in++;
94 }
95 return this->compression->process(this->compression, type, data);
96 }
97
98 METHOD(tls_protection_t, build, status_t,
99 private_tls_protection_t *this, tls_content_type_t *type, chunk_t *data)
100 {
101 status_t status;
102
103 status = this->compression->build(this->compression, type, data);
104 if (status == NEED_MORE)
105 {
106 if (*type == TLS_CHANGE_CIPHER_SPEC)
107 {
108 this->seq_out = 0;
109 return status;
110 }
111 if (this->aead_out)
112 {
113 if (!this->aead_out->encrypt(this->aead_out, this->version,
114 *type, this->seq_out, data))
115 {
116 DBG1(DBG_TLS, "TLS record encryption failed");
117 chunk_free(data);
118 return FAILED;
119 }
120 }
121 this->seq_out++;
122 }
123 return status;
124 }
125
126 METHOD(tls_protection_t, set_cipher, void,
127 private_tls_protection_t *this, bool inbound, tls_aead_t *aead)
128 {
129 if (inbound)
130 {
131 this->aead_in = aead;
132 }
133 else
134 {
135 this->aead_out = aead;
136 }
137 }
138
139 METHOD(tls_protection_t, set_version, void,
140 private_tls_protection_t *this, tls_version_t version)
141 {
142 this->version = version;
143 }
144
145 METHOD(tls_protection_t, destroy, void,
146 private_tls_protection_t *this)
147 {
148 free(this);
149 }
150
151 /**
152 * See header
153 */
154 tls_protection_t *tls_protection_create(tls_compression_t *compression,
155 tls_alert_t *alert)
156 {
157 private_tls_protection_t *this;
158
159 INIT(this,
160 .public = {
161 .process = _process,
162 .build = _build,
163 .set_cipher = _set_cipher,
164 .set_version = _set_version,
165 .destroy = _destroy,
166 },
167 .alert = alert,
168 .compression = compression,
169 );
170
171 return &this->public;
172 }