|
1 /* |
|
2 * Copyright (c) 2001-2006 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of the License "Eclipse Public License v1.0" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Nokia Corporation - initial contribution. |
|
11 * |
|
12 * Contributors: |
|
13 * |
|
14 * Description: EAP and WLAN authentication protocols. |
|
15 * |
|
16 */ |
|
17 |
|
18 |
|
19 // This is enumeration of EAPOL source code. |
|
20 #if defined(USE_EAP_MINIMUM_RELEASE_TRACES) |
|
21 #undef EAP_FILE_NUMBER_ENUM |
|
22 #define EAP_FILE_NUMBER_ENUM 131 |
|
23 #undef EAP_FILE_NUMBER_DATE |
|
24 #define EAP_FILE_NUMBER_DATE 1127594498 |
|
25 #endif //#if defined(USE_EAP_MINIMUM_RELEASE_TRACES) |
|
26 |
|
27 |
|
28 |
|
29 #include "eap_am_memory.h" |
|
30 #include "eap_tools.h" |
|
31 #include "eap_array.h" |
|
32 #include "tls_message.h" |
|
33 #include "tls_peap_types.h" |
|
34 #include "eap_automatic_variable.h" |
|
35 |
|
36 /** @file */ |
|
37 |
|
38 |
|
39 //-------------------------------------------------- |
|
40 |
|
41 EAP_FUNC_EXPORT tls_message_c::~tls_message_c() |
|
42 { |
|
43 EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
44 |
|
45 m_record_messages.reset(); |
|
46 |
|
47 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
48 } |
|
49 |
|
50 //-------------------------------------------------- |
|
51 |
|
52 EAP_FUNC_EXPORT tls_message_c::tls_message_c( |
|
53 abs_eap_am_tools_c * const tools, |
|
54 abs_tls_message_hash_c * const message_hash, |
|
55 abs_tls_apply_cipher_spec_c * const apply_cipher_spec, |
|
56 abs_tls_change_cipher_spec_c * change_cipher_spec, |
|
57 const bool is_client) |
|
58 : m_am_tools(tools) |
|
59 , m_message_hash(message_hash) |
|
60 , m_apply_cipher_spec(apply_cipher_spec) |
|
61 , m_change_cipher_spec(change_cipher_spec) |
|
62 , m_tls_message_data(tools) |
|
63 , m_received_eap_identifier(0ul) |
|
64 , m_analyse_index(0ul) |
|
65 , m_record_messages(tools) |
|
66 , m_is_client(is_client) |
|
67 , m_includes_tls_handshake_message(false) |
|
68 { |
|
69 EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
70 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
71 } |
|
72 |
|
73 //-------------------------------------------------- |
|
74 |
|
75 EAP_FUNC_EXPORT eap_status_e tls_message_c::reset() |
|
76 { |
|
77 EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
78 |
|
79 m_analyse_index = 0ul; |
|
80 m_received_eap_identifier = 0ul; |
|
81 m_includes_tls_handshake_message = false; |
|
82 |
|
83 eap_status_e status = m_record_messages.reset(); |
|
84 |
|
85 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
86 return EAP_STATUS_RETURN(m_am_tools, status); |
|
87 } |
|
88 |
|
89 //-------------------------------------------------- |
|
90 |
|
91 EAP_FUNC_EXPORT u32_t tls_message_c::get_analyse_index() const |
|
92 { |
|
93 EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
94 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
95 return m_analyse_index; |
|
96 } |
|
97 |
|
98 //-------------------------------------------------- |
|
99 |
|
100 EAP_FUNC_EXPORT void tls_message_c::save_analyse_index(const u32_t analyse_index) |
|
101 { |
|
102 EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
103 |
|
104 m_analyse_index = analyse_index; |
|
105 |
|
106 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
107 } |
|
108 |
|
109 //-------------------------------------------------- |
|
110 |
|
111 EAP_FUNC_EXPORT eap_status_e tls_message_c::set_tls_message_data( |
|
112 eap_variable_data_c * const tls_message_data, |
|
113 u8_t received_eap_identifier) |
|
114 { |
|
115 EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
116 |
|
117 eap_status_e status = m_tls_message_data.set_copy_of_buffer(tls_message_data); |
|
118 if (status != eap_status_ok) |
|
119 { |
|
120 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
121 return EAP_STATUS_RETURN(m_am_tools, status); |
|
122 } |
|
123 |
|
124 m_received_eap_identifier = received_eap_identifier; |
|
125 |
|
126 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
127 return EAP_STATUS_RETURN(m_am_tools, status); |
|
128 } |
|
129 |
|
130 //-------------------------------------------------- |
|
131 |
|
132 EAP_FUNC_EXPORT eap_variable_data_c * tls_message_c::get_tls_message_data() |
|
133 { |
|
134 EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
135 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
136 return &m_tls_message_data; |
|
137 } |
|
138 |
|
139 //-------------------------------------------------- |
|
140 |
|
141 EAP_FUNC_EXPORT u8_t tls_message_c::get_received_eap_identifier() |
|
142 { |
|
143 EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
144 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
145 return m_received_eap_identifier; |
|
146 } |
|
147 |
|
148 //-------------------------------------------------- |
|
149 |
|
150 EAP_FUNC_EXPORT eap_status_e tls_message_c::add_record_message( |
|
151 tls_record_message_c * const record, |
|
152 const bool free_record, |
|
153 const bool includes_tls_handshake_message) |
|
154 { |
|
155 EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
156 |
|
157 if (m_includes_tls_handshake_message == false) |
|
158 { |
|
159 m_includes_tls_handshake_message = includes_tls_handshake_message; |
|
160 } |
|
161 |
|
162 eap_status_e status = m_record_messages.add_object(record, free_record); |
|
163 |
|
164 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
165 return EAP_STATUS_RETURN(m_am_tools, status); |
|
166 } |
|
167 |
|
168 //-------------------------------------------------- |
|
169 |
|
170 EAP_FUNC_EXPORT eap_status_e tls_message_c::fragment_tls_records( |
|
171 tls_record_message_c * const tls_record_message, |
|
172 eap_array_c<tls_record_message_c> * const tls_fragments) |
|
173 { |
|
174 EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
175 |
|
176 eap_status_e status = eap_status_ok; |
|
177 |
|
178 // Here we assume data included in tls_record_message does not include TLS-record header. |
|
179 // Only data TLS-protocol messages are included. All TLS-protocol messages are same protocol. |
|
180 // This function fragments TLS-protocol messages to one or more TLS-record messages. |
|
181 |
|
182 u32_t size_of_data = tls_record_message->get_data_length(); |
|
183 u32_t offset_of_data = 0ul; |
|
184 |
|
185 while(size_of_data > 0ul) |
|
186 { |
|
187 tls_record_message_c * const fragment = new tls_record_message_c( |
|
188 m_am_tools, m_message_hash, m_is_client); |
|
189 |
|
190 eap_automatic_variable_c<tls_record_message_c> |
|
191 automatic_fragment(m_am_tools, fragment); |
|
192 |
|
193 if (fragment == 0 |
|
194 || fragment->get_is_valid() == false) |
|
195 { |
|
196 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
197 return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error); |
|
198 } |
|
199 |
|
200 u32_t fragment_length = size_of_data; |
|
201 if (fragment_length > TLS_PEAP_MAX_RECORD_FRAGMENT_LENGTH) |
|
202 { |
|
203 fragment_length = TLS_PEAP_MAX_RECORD_FRAGMENT_LENGTH; |
|
204 } |
|
205 |
|
206 |
|
207 // Adds TLS-record header. |
|
208 status = fragment->get_record_message_data()->set_buffer_length(tls_record_header_c::get_header_length()+fragment_length); |
|
209 if (status != eap_status_ok) |
|
210 { |
|
211 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
212 return EAP_STATUS_RETURN(m_am_tools, status); |
|
213 } |
|
214 |
|
215 tls_record_header_c tmp_tls_record_header_on_tls_message_buffer( |
|
216 m_am_tools, |
|
217 fragment->get_record_message_data()->get_buffer(tls_record_header_c::get_header_length()+fragment_length), |
|
218 tls_record_header_c::get_header_length()+fragment_length); |
|
219 |
|
220 if (tmp_tls_record_header_on_tls_message_buffer.get_is_valid() == false) |
|
221 { |
|
222 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
223 return EAP_STATUS_RETURN(m_am_tools, eap_status_too_long_message); |
|
224 } |
|
225 |
|
226 // Note this is the length of the TLS-record header. |
|
227 fragment->get_record_message_data()->set_data_length(tls_record_header_c::get_header_length()); |
|
228 fragment->set_protocol(tls_record_message->get_protocol()); |
|
229 fragment->set_version(tls_record_message->get_version()); |
|
230 // Note this is the length of the TLS-record header and TLS-record data. |
|
231 // The length of the TLS-record data is the length of the fragment. |
|
232 fragment->add_data_length(tls_record_header_c::get_header_length()+fragment_length); |
|
233 fragment->set_tls_record_header_is_included(true); |
|
234 |
|
235 tmp_tls_record_header_on_tls_message_buffer.reset_header(0ul, tls_record_message->get_version()); |
|
236 tmp_tls_record_header_on_tls_message_buffer.set_protocol(tls_record_message->get_protocol()); |
|
237 tmp_tls_record_header_on_tls_message_buffer.set_data_length(static_cast<u16_t>(fragment_length)); |
|
238 |
|
239 EAP_TRACE_DEBUG(m_am_tools, TRACE_FLAGS_DEFAULT, (EAPL("\n"))); |
|
240 EAP_TRACE_DEBUG( |
|
241 m_am_tools, |
|
242 TRACE_FLAGS_DEFAULT, |
|
243 (EAPL("TLS: %s: tls_message_c::fragment_tls_records(): %s fragment %d bytes from %d bytes.\n"), |
|
244 (m_is_client == true ? "client": "server"), |
|
245 tmp_tls_record_header_on_tls_message_buffer.get_tls_protocol_string(), |
|
246 fragment_length, |
|
247 tls_record_message->get_data_length())); |
|
248 |
|
249 // Adds TLS-record data, this includes TLS-protocol messages. |
|
250 status = fragment->get_record_message_data()->add_data( |
|
251 tls_record_message->get_record_message_data()->get_data_offset( |
|
252 offset_of_data, fragment_length), |
|
253 fragment_length); |
|
254 if (status != eap_status_ok) |
|
255 { |
|
256 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
257 return EAP_STATUS_RETURN(m_am_tools, status); |
|
258 } |
|
259 |
|
260 size_of_data -= fragment_length; |
|
261 offset_of_data += fragment_length; |
|
262 |
|
263 automatic_fragment.do_not_free_variable(); |
|
264 |
|
265 status = tls_fragments->add_object(fragment, true); |
|
266 if (status != eap_status_ok) |
|
267 { |
|
268 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
269 return EAP_STATUS_RETURN(m_am_tools, status); |
|
270 } |
|
271 |
|
272 } // while() |
|
273 |
|
274 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
275 return EAP_STATUS_RETURN(m_am_tools, status); |
|
276 } |
|
277 |
|
278 //-------------------------------------------------- |
|
279 |
|
280 EAP_FUNC_EXPORT eap_status_e tls_message_c::add_message_data( |
|
281 eap_variable_data_c * const tls_message_buffer, |
|
282 bool * const includes_tls_handshake_message) |
|
283 { |
|
284 EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
285 |
|
286 eap_status_e status = eap_status_ok; |
|
287 |
|
288 tls_message_buffer->reset(); |
|
289 status = tls_message_buffer->set_buffer_length(TLS_PEAP_DEFAULT_RECORD_LENGTH); |
|
290 if (status != eap_status_ok) |
|
291 { |
|
292 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
293 return EAP_STATUS_RETURN(m_am_tools, status); |
|
294 } |
|
295 |
|
296 for (u32_t ind = 0ul; ind < m_record_messages.get_object_count(); ind++) |
|
297 { |
|
298 tls_record_message_c * const tls_record_message = m_record_messages.get_object(ind); |
|
299 if (tls_record_message == 0) |
|
300 { |
|
301 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
302 return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error); |
|
303 } |
|
304 |
|
305 if (tls_record_message->get_record_message_data()->get_is_valid() == false |
|
306 || tls_record_message->get_record_message_data()->get_buffer_length() < TLS_PEAP_DEFAULT_RECORD_LENGTH) |
|
307 { |
|
308 status = tls_record_message->get_record_message_data()->set_buffer_length(TLS_PEAP_DEFAULT_RECORD_LENGTH); |
|
309 if (status != eap_status_ok) |
|
310 { |
|
311 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
312 return EAP_STATUS_RETURN(m_am_tools, status); |
|
313 } |
|
314 } |
|
315 |
|
316 tls_record_message->get_record_message_data()->set_data_length(0ul); |
|
317 |
|
318 // This function creates data of TLS-protocol message to internal buffer (tls_record_message->get_record_message_data()). |
|
319 status = tls_record_message->add_message_data(); |
|
320 if (status != eap_status_ok) |
|
321 { |
|
322 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
323 return EAP_STATUS_RETURN(m_am_tools, status); |
|
324 } |
|
325 |
|
326 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
|
327 |
|
328 EAP_ASSERT(tls_record_message->get_tls_record_header_is_included() == false); |
|
329 |
|
330 EAP_TRACE_DATA_DEBUG( |
|
331 m_am_tools, |
|
332 EAP_TRACE_FLAGS_MESSAGE_DATA, |
|
333 (EAPL("TLS-record data"), |
|
334 tls_record_message->get_record_message_data()->get_data( |
|
335 tls_record_message->get_record_message_data()->get_data_length()), |
|
336 tls_record_message->get_record_message_data()->get_data_length())); |
|
337 |
|
338 // Fragmentation checks the TLS-record is not too long, data more than 2^14 bytes. |
|
339 // It fragments TLS-record to two or more TLS-records. |
|
340 // TLS-records could be stored to object of type of eap_array_c<tls_record_message_c>. |
|
341 // In a case the TLS-record cannot be fragmented the whole TLS-message must be dropped. |
|
342 eap_array_c<tls_record_message_c> tls_fragments(m_am_tools); |
|
343 status = fragment_tls_records( |
|
344 tls_record_message, |
|
345 &tls_fragments); |
|
346 if (status != eap_status_ok) |
|
347 { |
|
348 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
349 return EAP_STATUS_RETURN(m_am_tools, status); |
|
350 } |
|
351 |
|
352 // After the fragmentation cipher suite can be applied to every fragment. |
|
353 for (u32_t ind_frag = 0ul; ind_frag < tls_fragments.get_object_count(); ind_frag++) |
|
354 { |
|
355 tls_record_message_c * const fragment = tls_fragments.get_object(ind_frag); |
|
356 if (fragment == 0) |
|
357 { |
|
358 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
359 return EAP_STATUS_RETURN(m_am_tools, eap_status_process_general_error); |
|
360 } |
|
361 |
|
362 EAP_ASSERT(fragment->get_data_length() == fragment->get_record_message_data()->get_data_length()); |
|
363 |
|
364 status = m_apply_cipher_spec->apply_send_cipher_suite(fragment->get_record_message_data()); |
|
365 if (status != eap_status_ok) |
|
366 { |
|
367 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
368 return EAP_STATUS_RETURN(m_am_tools, status); |
|
369 } |
|
370 |
|
371 if (ind_frag == 0ul) |
|
372 { |
|
373 if (fragment->get_protocol() == tls_record_protocol_change_cipher_spec) |
|
374 { |
|
375 // This is the right place to change the send cipher spec. |
|
376 status = m_change_cipher_spec->change_cipher_spec(true); |
|
377 if (status != eap_status_ok) |
|
378 { |
|
379 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
380 return EAP_STATUS_RETURN(m_am_tools, status); |
|
381 } |
|
382 } |
|
383 } |
|
384 |
|
385 status = tls_message_buffer->add_data(fragment->get_record_message_data()); |
|
386 if (status != eap_status_ok) |
|
387 { |
|
388 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
389 return EAP_STATUS_RETURN(m_am_tools, status); |
|
390 } |
|
391 } // for() |
|
392 |
|
393 } // for() |
|
394 |
|
395 *includes_tls_handshake_message = m_includes_tls_handshake_message; |
|
396 |
|
397 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
398 return EAP_STATUS_RETURN(m_am_tools, status); |
|
399 } |
|
400 |
|
401 //-------------------------------------------------- |
|
402 |
|
403 EAP_FUNC_EXPORT u32_t tls_message_c::get_record_message_count() const |
|
404 { |
|
405 EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
406 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
407 return m_record_messages.get_object_count(); |
|
408 } |
|
409 |
|
410 //-------------------------------------------------- |
|
411 |
|
412 EAP_FUNC_EXPORT tls_record_message_c * tls_message_c::get_record_message( |
|
413 const u32_t index) const |
|
414 { |
|
415 EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
416 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
417 return m_record_messages.get_object(index); |
|
418 } |
|
419 |
|
420 //-------------------------------------------------- |
|
421 |
|
422 EAP_FUNC_EXPORT eap_status_e tls_message_c::remove_record_message( |
|
423 const u32_t index) |
|
424 { |
|
425 EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
426 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
427 return m_record_messages.remove_object(index); |
|
428 } |
|
429 |
|
430 //-------------------------------------------------- |
|
431 |
|
432 EAP_FUNC_EXPORT tls_record_message_c * tls_message_c::get_last_record_message() const |
|
433 { |
|
434 EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
435 EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT); |
|
436 return m_record_messages.get_last_object(); |
|
437 } |
|
438 |
|
439 //-------------------------------------------------- |
|
440 |
|
441 |
|
442 |
|
443 // End. |