]>
Commit | Line | Data |
---|---|---|
3c2bdd7d | 1 | # Copyright 2016-2021 The OpenSSL Project Authors. All Rights Reserved. |
631c1206 | 2 | # |
9059ab42 | 3 | # Licensed under the Apache License 2.0 (the "License"). You may not use |
ac3d0e13 RS |
4 | # this file except in compliance with the License. You can obtain a copy |
5 | # in the file LICENSE in the source distribution or at | |
6 | # https://www.openssl.org/source/license.html | |
631c1206 MC |
7 | |
8 | use strict; | |
9 | ||
10 | package TLSProxy::Message; | |
11 | ||
f460e839 MC |
12 | use TLSProxy::Alert; |
13 | ||
631c1206 MC |
14 | use constant TLS_MESSAGE_HEADER_LENGTH => 4; |
15 | ||
16 | #Message types | |
17 | use constant { | |
18 | MT_HELLO_REQUEST => 0, | |
19 | MT_CLIENT_HELLO => 1, | |
20 | MT_SERVER_HELLO => 2, | |
21 | MT_NEW_SESSION_TICKET => 4, | |
e46f2334 | 22 | MT_ENCRYPTED_EXTENSIONS => 8, |
631c1206 MC |
23 | MT_CERTIFICATE => 11, |
24 | MT_SERVER_KEY_EXCHANGE => 12, | |
25 | MT_CERTIFICATE_REQUEST => 13, | |
26 | MT_SERVER_HELLO_DONE => 14, | |
27 | MT_CERTIFICATE_VERIFY => 15, | |
28 | MT_CLIENT_KEY_EXCHANGE => 16, | |
29 | MT_FINISHED => 20, | |
30 | MT_CERTIFICATE_STATUS => 22, | |
b67cb09f | 31 | MT_COMPRESSED_CERTIFICATE => 25, |
631c1206 MC |
32 | MT_NEXT_PROTO => 67 |
33 | }; | |
8af538e5 MC |
34 | |
35 | #Alert levels | |
36 | use constant { | |
37 | AL_LEVEL_WARN => 1, | |
38 | AL_LEVEL_FATAL => 2 | |
39 | }; | |
40 | ||
41 | #Alert descriptions | |
42 | use constant { | |
c3fd55d4 | 43 | AL_DESC_CLOSE_NOTIFY => 0, |
a2a0c86b | 44 | AL_DESC_UNEXPECTED_MESSAGE => 10, |
9b287d53 | 45 | AL_DESC_ILLEGAL_PARAMETER => 47, |
a2a0c86b | 46 | AL_DESC_NO_RENEGOTIATION => 100 |
8af538e5 MC |
47 | }; |
48 | ||
631c1206 MC |
49 | my %message_type = ( |
50 | MT_HELLO_REQUEST, "HelloRequest", | |
51 | MT_CLIENT_HELLO, "ClientHello", | |
52 | MT_SERVER_HELLO, "ServerHello", | |
53 | MT_NEW_SESSION_TICKET, "NewSessionTicket", | |
e46f2334 | 54 | MT_ENCRYPTED_EXTENSIONS, "EncryptedExtensions", |
631c1206 MC |
55 | MT_CERTIFICATE, "Certificate", |
56 | MT_SERVER_KEY_EXCHANGE, "ServerKeyExchange", | |
57 | MT_CERTIFICATE_REQUEST, "CertificateRequest", | |
58 | MT_SERVER_HELLO_DONE, "ServerHelloDone", | |
59 | MT_CERTIFICATE_VERIFY, "CertificateVerify", | |
60 | MT_CLIENT_KEY_EXCHANGE, "ClientKeyExchange", | |
61 | MT_FINISHED, "Finished", | |
62 | MT_CERTIFICATE_STATUS, "CertificateStatus", | |
b67cb09f | 63 | MT_COMPRESSED_CERTIFICATE, "CompressedCertificate", |
631c1206 MC |
64 | MT_NEXT_PROTO, "NextProto" |
65 | ); | |
66 | ||
aa474d1f | 67 | use constant { |
9ce3ed2a | 68 | EXT_SERVER_NAME => 0, |
cf72c757 | 69 | EXT_MAX_FRAGMENT_LENGTH => 1, |
aa474d1f | 70 | EXT_STATUS_REQUEST => 5, |
5a8e54d9 | 71 | EXT_SUPPORTED_GROUPS => 10, |
9ce3ed2a MC |
72 | EXT_EC_POINT_FORMATS => 11, |
73 | EXT_SRP => 12, | |
74 | EXT_SIG_ALGS => 13, | |
75 | EXT_USE_SRTP => 14, | |
76 | EXT_ALPN => 16, | |
77 | EXT_SCT => 18, | |
3c95ef22 TS |
78 | EXT_CLIENT_CERT_TYPE => 19, |
79 | EXT_SERVER_CERT_TYPE => 20, | |
9ce3ed2a | 80 | EXT_PADDING => 21, |
aa474d1f EK |
81 | EXT_ENCRYPT_THEN_MAC => 22, |
82 | EXT_EXTENDED_MASTER_SECRET => 23, | |
b67cb09f | 83 | EXT_COMPRESS_CERTIFICATE => 27, |
aa474d1f | 84 | EXT_SESSION_TICKET => 35, |
f27f5cd4 | 85 | EXT_KEY_SHARE => 51, |
1c361b4a | 86 | EXT_PSK => 41, |
9ce3ed2a | 87 | EXT_SUPPORTED_VERSIONS => 43, |
ee700226 | 88 | EXT_COOKIE => 44, |
b2f7e8c0 | 89 | EXT_PSK_KEX_MODES => 45, |
9d75dce3 | 90 | EXT_POST_HANDSHAKE_AUTH => 49, |
3e524bf2 | 91 | EXT_SIG_ALGS_CERT => 50, |
9ce3ed2a MC |
92 | EXT_RENEGOTIATE => 65281, |
93 | EXT_NPN => 13172, | |
9effc496 | 94 | EXT_CRYPTOPRO_BUG_EXTENSION => 0xfde8, |
5e3766e2 | 95 | EXT_UNKNOWN => 0xfffe, |
717afd93 MC |
96 | #Unknown extension that should appear last |
97 | EXT_FORCE_LAST => 0xffff | |
aa474d1f EK |
98 | }; |
99 | ||
35e742ec MC |
100 | # SignatureScheme of TLS 1.3 from: |
101 | # https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-signaturescheme | |
d499a3e1 BK |
102 | # We have to manually grab the SHA224 equivalents from the old registry |
103 | use constant { | |
104 | SIG_ALG_RSA_PKCS1_SHA256 => 0x0401, | |
105 | SIG_ALG_RSA_PKCS1_SHA384 => 0x0501, | |
106 | SIG_ALG_RSA_PKCS1_SHA512 => 0x0601, | |
107 | SIG_ALG_ECDSA_SECP256R1_SHA256 => 0x0403, | |
108 | SIG_ALG_ECDSA_SECP384R1_SHA384 => 0x0503, | |
109 | SIG_ALG_ECDSA_SECP521R1_SHA512 => 0x0603, | |
9e6a3202 MC |
110 | SIG_ALG_RSA_PSS_RSAE_SHA256 => 0x0804, |
111 | SIG_ALG_RSA_PSS_RSAE_SHA384 => 0x0805, | |
112 | SIG_ALG_RSA_PSS_RSAE_SHA512 => 0x0806, | |
d499a3e1 BK |
113 | SIG_ALG_ED25519 => 0x0807, |
114 | SIG_ALG_ED448 => 0x0808, | |
9e6a3202 MC |
115 | SIG_ALG_RSA_PSS_PSS_SHA256 => 0x0809, |
116 | SIG_ALG_RSA_PSS_PSS_SHA384 => 0x080a, | |
117 | SIG_ALG_RSA_PSS_PSS_SHA512 => 0x080b, | |
d499a3e1 BK |
118 | SIG_ALG_RSA_PKCS1_SHA1 => 0x0201, |
119 | SIG_ALG_ECDSA_SHA1 => 0x0203, | |
120 | SIG_ALG_DSA_SHA1 => 0x0202, | |
121 | SIG_ALG_DSA_SHA256 => 0x0402, | |
122 | SIG_ALG_DSA_SHA384 => 0x0502, | |
123 | SIG_ALG_DSA_SHA512 => 0x0602, | |
124 | OSSL_SIG_ALG_RSA_PKCS1_SHA224 => 0x0301, | |
125 | OSSL_SIG_ALG_DSA_SHA224 => 0x0302, | |
126 | OSSL_SIG_ALG_ECDSA_SHA224 => 0x0303 | |
127 | }; | |
128 | ||
397f4f78 | 129 | use constant { |
9b287d53 | 130 | CIPHER_RSA_WITH_AES_128_CBC_SHA => 0x002f, |
79d8c167 | 131 | CIPHER_DHE_RSA_AES_128_SHA => 0x0033, |
c35cb287 MC |
132 | CIPHER_ADH_AES_128_SHA => 0x0034, |
133 | CIPHER_TLS13_AES_128_GCM_SHA256 => 0x1301, | |
134 | CIPHER_TLS13_AES_256_GCM_SHA384 => 0x1302 | |
397f4f78 MC |
135 | }; |
136 | ||
dc5bcb88 MC |
137 | use constant { |
138 | CLIENT => 0, | |
139 | SERVER => 1 | |
140 | }; | |
141 | ||
631c1206 MC |
142 | my $payload = ""; |
143 | my $messlen = -1; | |
144 | my $mt; | |
145 | my $startoffset = -1; | |
146 | my $server = 0; | |
147 | my $success = 0; | |
148 | my $end = 0; | |
149 | my @message_rec_list = (); | |
150 | my @message_frag_lens = (); | |
a1accbb1 | 151 | my $ciphersuite = 0; |
1c361b4a | 152 | my $successondata = 0; |
f460e839 | 153 | my $alert; |
631c1206 MC |
154 | |
155 | sub clear | |
156 | { | |
157 | $payload = ""; | |
158 | $messlen = -1; | |
159 | $startoffset = -1; | |
160 | $server = 0; | |
161 | $success = 0; | |
162 | $end = 0; | |
1c361b4a | 163 | $successondata = 0; |
631c1206 MC |
164 | @message_rec_list = (); |
165 | @message_frag_lens = (); | |
f460e839 | 166 | $alert = undef; |
631c1206 MC |
167 | } |
168 | ||
169 | #Class method to extract messages from a record | |
170 | sub get_messages | |
171 | { | |
172 | my $class = shift; | |
173 | my $serverin = shift; | |
174 | my $record = shift; | |
175 | my @messages = (); | |
176 | my $message; | |
177 | ||
a1accbb1 MC |
178 | @message_frag_lens = (); |
179 | ||
631c1206 MC |
180 | if ($serverin != $server && length($payload) != 0) { |
181 | die "Changed peer, but we still have fragment data\n"; | |
182 | } | |
183 | $server = $serverin; | |
184 | ||
185 | if ($record->content_type == TLSProxy::Record::RT_CCS) { | |
186 | if ($payload ne "") { | |
187 | #We can't handle this yet | |
188 | die "CCS received before message data complete\n"; | |
189 | } | |
be60b10a MC |
190 | if (!TLSProxy::Proxy->is_tls13()) { |
191 | if ($server) { | |
192 | TLSProxy::Record->server_encrypting(1); | |
193 | } else { | |
194 | TLSProxy::Record->client_encrypting(1); | |
195 | } | |
631c1206 MC |
196 | } |
197 | } elsif ($record->content_type == TLSProxy::Record::RT_HANDSHAKE) { | |
198 | if ($record->len == 0 || $record->len_real == 0) { | |
199 | print " Message truncated\n"; | |
200 | } else { | |
201 | my $recoffset = 0; | |
202 | ||
203 | if (length $payload > 0) { | |
204 | #We are continuing processing a message started in a previous | |
205 | #record. Add this record to the list associated with this | |
206 | #message | |
207 | push @message_rec_list, $record; | |
208 | ||
209 | if ($messlen <= length($payload)) { | |
210 | #Shouldn't happen | |
211 | die "Internal error: invalid messlen: ".$messlen | |
212 | ." payload length:".length($payload)."\n"; | |
213 | } | |
214 | if (length($payload) + $record->decrypt_len >= $messlen) { | |
215 | #We can complete the message with this record | |
216 | $recoffset = $messlen - length($payload); | |
217 | $payload .= substr($record->decrypt_data, 0, $recoffset); | |
218 | push @message_frag_lens, $recoffset; | |
219 | $message = create_message($server, $mt, $payload, | |
220 | $startoffset); | |
221 | push @messages, $message; | |
222 | ||
631c1206 MC |
223 | $payload = ""; |
224 | } else { | |
225 | #This is just part of the total message | |
226 | $payload .= $record->decrypt_data; | |
227 | $recoffset = $record->decrypt_len; | |
228 | push @message_frag_lens, $record->decrypt_len; | |
229 | } | |
230 | print " Partial message data read: ".$recoffset." bytes\n"; | |
231 | } | |
232 | ||
233 | while ($record->decrypt_len > $recoffset) { | |
234 | #We are at the start of a new message | |
235 | if ($record->decrypt_len - $recoffset < 4) { | |
236 | #Whilst technically probably valid we can't cope with this | |
237 | die "End of record in the middle of a message header\n"; | |
238 | } | |
239 | @message_rec_list = ($record); | |
240 | my $lenhi; | |
241 | my $lenlo; | |
242 | ($mt, $lenhi, $lenlo) = unpack('CnC', | |
243 | substr($record->decrypt_data, | |
244 | $recoffset)); | |
245 | $messlen = ($lenhi << 8) | $lenlo; | |
246 | print " Message type: $message_type{$mt}\n"; | |
247 | print " Message Length: $messlen\n"; | |
248 | $startoffset = $recoffset; | |
249 | $recoffset += 4; | |
250 | $payload = ""; | |
df443918 | 251 | |
d70bde88 | 252 | if ($recoffset <= $record->decrypt_len) { |
631c1206 MC |
253 | #Some payload data is present in this record |
254 | if ($record->decrypt_len - $recoffset >= $messlen) { | |
255 | #We can complete the message with this record | |
256 | $payload .= substr($record->decrypt_data, $recoffset, | |
257 | $messlen); | |
258 | $recoffset += $messlen; | |
259 | push @message_frag_lens, $messlen; | |
260 | $message = create_message($server, $mt, $payload, | |
261 | $startoffset); | |
262 | push @messages, $message; | |
263 | ||
631c1206 MC |
264 | $payload = ""; |
265 | } else { | |
266 | #This is just part of the total message | |
267 | $payload .= substr($record->decrypt_data, $recoffset, | |
268 | $record->decrypt_len - $recoffset); | |
269 | $recoffset = $record->decrypt_len; | |
270 | push @message_frag_lens, $recoffset; | |
271 | } | |
272 | } | |
273 | } | |
274 | } | |
275 | } elsif ($record->content_type == TLSProxy::Record::RT_APPLICATION_DATA) { | |
276 | print " [ENCRYPTED APPLICATION DATA]\n"; | |
277 | print " [".$record->decrypt_data."]\n"; | |
1c361b4a MC |
278 | |
279 | if ($successondata) { | |
280 | $success = 1; | |
281 | $end = 1; | |
282 | } | |
631c1206 | 283 | } elsif ($record->content_type == TLSProxy::Record::RT_ALERT) { |
8af538e5 | 284 | my ($alertlev, $alertdesc) = unpack('CC', $record->decrypt_data); |
3f473b93 | 285 | print " [$alertlev, $alertdesc]\n"; |
8af538e5 MC |
286 | #A CloseNotify from the client indicates we have finished successfully |
287 | #(we assume) | |
8523288e | 288 | if (!$end && !$server && $alertlev == AL_LEVEL_WARN |
8af538e5 MC |
289 | && $alertdesc == AL_DESC_CLOSE_NOTIFY) { |
290 | $success = 1; | |
291 | } | |
3f473b93 AP |
292 | #Fatal or close notify alerts end the test |
293 | if ($alertlev == AL_LEVEL_FATAL || $alertdesc == AL_DESC_CLOSE_NOTIFY) { | |
294 | $end = 1; | |
295 | } | |
f460e839 MC |
296 | $alert = TLSProxy::Alert->new( |
297 | $server, | |
298 | $record->encrypted, | |
299 | $alertlev, | |
300 | $alertdesc); | |
631c1206 MC |
301 | } |
302 | ||
303 | return @messages; | |
304 | } | |
305 | ||
306 | #Function to work out which sub-class we need to create and then | |
307 | #construct it | |
308 | sub create_message | |
309 | { | |
310 | my ($server, $mt, $data, $startoffset) = @_; | |
311 | my $message; | |
312 | ||
313 | #We only support ClientHello in this version...needs to be extended for | |
314 | #others | |
315 | if ($mt == MT_CLIENT_HELLO) { | |
316 | $message = TLSProxy::ClientHello->new( | |
317 | $server, | |
318 | $data, | |
319 | [@message_rec_list], | |
320 | $startoffset, | |
321 | [@message_frag_lens] | |
322 | ); | |
323 | $message->parse(); | |
a1accbb1 MC |
324 | } elsif ($mt == MT_SERVER_HELLO) { |
325 | $message = TLSProxy::ServerHello->new( | |
326 | $server, | |
327 | $data, | |
328 | [@message_rec_list], | |
329 | $startoffset, | |
330 | [@message_frag_lens] | |
331 | ); | |
9ce3ed2a MC |
332 | $message->parse(); |
333 | } elsif ($mt == MT_ENCRYPTED_EXTENSIONS) { | |
334 | $message = TLSProxy::EncryptedExtensions->new( | |
335 | $server, | |
336 | $data, | |
337 | [@message_rec_list], | |
338 | $startoffset, | |
339 | [@message_frag_lens] | |
340 | ); | |
e96e0f8e MC |
341 | $message->parse(); |
342 | } elsif ($mt == MT_CERTIFICATE) { | |
343 | $message = TLSProxy::Certificate->new( | |
344 | $server, | |
345 | $data, | |
346 | [@message_rec_list], | |
347 | $startoffset, | |
348 | [@message_frag_lens] | |
349 | ); | |
adb403de | 350 | $message->parse(); |
dc5bcb88 MC |
351 | } elsif ($mt == MT_CERTIFICATE_REQUEST) { |
352 | $message = TLSProxy::CertificateRequest->new( | |
353 | $server, | |
354 | $data, | |
355 | [@message_rec_list], | |
356 | $startoffset, | |
357 | [@message_frag_lens] | |
358 | ); | |
359 | $message->parse(); | |
adb403de MC |
360 | } elsif ($mt == MT_CERTIFICATE_VERIFY) { |
361 | $message = TLSProxy::CertificateVerify->new( | |
362 | $server, | |
363 | $data, | |
364 | [@message_rec_list], | |
365 | $startoffset, | |
366 | [@message_frag_lens] | |
367 | ); | |
a1accbb1 MC |
368 | $message->parse(); |
369 | } elsif ($mt == MT_SERVER_KEY_EXCHANGE) { | |
370 | $message = TLSProxy::ServerKeyExchange->new( | |
371 | $server, | |
372 | $data, | |
373 | [@message_rec_list], | |
374 | $startoffset, | |
375 | [@message_frag_lens] | |
7f6d90ac EK |
376 | ); |
377 | $message->parse(); | |
378 | } elsif ($mt == MT_NEW_SESSION_TICKET) { | |
379 | $message = TLSProxy::NewSessionTicket->new( | |
380 | $server, | |
381 | $data, | |
382 | [@message_rec_list], | |
383 | $startoffset, | |
384 | [@message_frag_lens] | |
a1accbb1 MC |
385 | ); |
386 | $message->parse(); | |
631c1206 MC |
387 | } else { |
388 | #Unknown message type | |
389 | $message = TLSProxy::Message->new( | |
390 | $server, | |
391 | $mt, | |
392 | $data, | |
393 | [@message_rec_list], | |
394 | $startoffset, | |
395 | [@message_frag_lens] | |
396 | ); | |
397 | } | |
398 | ||
399 | return $message; | |
400 | } | |
401 | ||
402 | sub end | |
403 | { | |
404 | my $class = shift; | |
405 | return $end; | |
406 | } | |
407 | sub success | |
408 | { | |
409 | my $class = shift; | |
410 | return $success; | |
411 | } | |
a1accbb1 MC |
412 | sub fail |
413 | { | |
414 | my $class = shift; | |
415 | return !$success && $end; | |
416 | } | |
f460e839 MC |
417 | |
418 | sub alert | |
419 | { | |
420 | return $alert; | |
421 | } | |
422 | ||
631c1206 MC |
423 | sub new |
424 | { | |
425 | my $class = shift; | |
426 | my ($server, | |
427 | $mt, | |
428 | $data, | |
429 | $records, | |
430 | $startoffset, | |
431 | $message_frag_lens) = @_; | |
df443918 | 432 | |
631c1206 MC |
433 | my $self = { |
434 | server => $server, | |
435 | data => $data, | |
436 | records => $records, | |
437 | mt => $mt, | |
438 | startoffset => $startoffset, | |
9effc496 MC |
439 | message_frag_lens => $message_frag_lens, |
440 | dupext => -1 | |
631c1206 MC |
441 | }; |
442 | ||
443 | return bless $self, $class; | |
444 | } | |
445 | ||
a1accbb1 MC |
446 | sub ciphersuite |
447 | { | |
448 | my $class = shift; | |
449 | if (@_) { | |
450 | $ciphersuite = shift; | |
451 | } | |
452 | return $ciphersuite; | |
453 | } | |
454 | ||
631c1206 | 455 | #Update all the underlying records with the modified data from this message |
ae937a09 | 456 | #Note: Only supports TLSv1.3 and ETM encryption |
631c1206 MC |
457 | sub repack |
458 | { | |
459 | my $self = shift; | |
460 | my $msgdata; | |
461 | ||
462 | my $numrecs = $#{$self->records}; | |
463 | ||
464 | $self->set_message_contents(); | |
465 | ||
466 | my $lenhi; | |
467 | my $lenlo; | |
468 | ||
469 | $lenlo = length($self->data) & 0xff; | |
470 | $lenhi = length($self->data) >> 8; | |
4deefd65 | 471 | $msgdata = pack('CnC', $self->mt, $lenhi, $lenlo).$self->data; |
631c1206 | 472 | |
631c1206 MC |
473 | if ($numrecs == 0) { |
474 | #The message is fully contained within one record | |
475 | my ($rec) = @{$self->records}; | |
476 | my $recdata = $rec->decrypt_data; | |
477 | ||
cf7f8592 EK |
478 | my $old_length; |
479 | ||
480 | # We use empty message_frag_lens to indicates that pre-repacking, | |
481 | # the message wasn't present. The first fragment length doesn't include | |
482 | # the TLS header, so we need to check and compute the right length. | |
483 | if (@{$self->message_frag_lens}) { | |
484 | $old_length = ${$self->message_frag_lens}[0] + | |
485 | TLS_MESSAGE_HEADER_LENGTH; | |
486 | } else { | |
487 | $old_length = 0; | |
631c1206 MC |
488 | } |
489 | ||
cf7f8592 EK |
490 | my $prefix = substr($recdata, 0, $self->startoffset); |
491 | my $suffix = substr($recdata, $self->startoffset + $old_length); | |
492 | ||
493 | $rec->decrypt_data($prefix.($msgdata).($suffix)); | |
494 | # TODO(openssl-team): don't keep explicit lengths. | |
495 | # (If a length override is ever needed to construct invalid packets, | |
496 | # use an explicit override field instead.) | |
497 | $rec->decrypt_len(length($rec->decrypt_data)); | |
ae937a09 MC |
498 | # Only support re-encryption for TLSv1.3 and ETM. |
499 | if ($rec->encrypted()) { | |
500 | if (TLSProxy::Proxy->is_tls13()) { | |
501 | #Add content type (1 byte) and 16 tag bytes | |
502 | $rec->data($rec->decrypt_data | |
503 | .pack("C", TLSProxy::Record::RT_HANDSHAKE).("\0"x16)); | |
504 | } elsif ($rec->etm()) { | |
505 | my $data = $rec->decrypt_data; | |
506 | #Add padding | |
507 | my $padval = length($data) % 16; | |
508 | $padval = 15 - $padval; | |
509 | for (0..$padval) { | |
510 | $data .= pack("C", $padval); | |
511 | } | |
512 | ||
513 | #Add MAC. Assumed to be 20 bytes | |
514 | foreach my $macval (0..19) { | |
515 | $data .= pack("C", $macval); | |
516 | } | |
517 | ||
518 | if ($rec->version() >= TLSProxy::Record::VERS_TLS_1_1) { | |
519 | #Explicit IV | |
520 | $data = ("\0"x16).$data; | |
521 | } | |
522 | $rec->data($data); | |
523 | } else { | |
524 | die "Unsupported encryption: No ETM"; | |
525 | } | |
357d096a MC |
526 | } else { |
527 | $rec->data($rec->decrypt_data); | |
528 | } | |
ae937a09 | 529 | $rec->len(length($rec->data)); |
631c1206 MC |
530 | |
531 | #Update the fragment len in case we changed it above | |
532 | ${$self->message_frag_lens}[0] = length($msgdata) | |
533 | - TLS_MESSAGE_HEADER_LENGTH; | |
534 | return; | |
535 | } | |
536 | ||
537 | #Note we don't currently support changing a fragmented message length | |
538 | my $recctr = 0; | |
539 | my $datadone = 0; | |
540 | foreach my $rec (@{$self->records}) { | |
541 | my $recdata = $rec->decrypt_data; | |
542 | if ($recctr == 0) { | |
543 | #This is the first record | |
544 | my $remainlen = length($recdata) - $self->startoffset; | |
545 | $rec->data(substr($recdata, 0, $self->startoffset) | |
546 | .substr(($msgdata), 0, $remainlen)); | |
547 | $datadone += $remainlen; | |
548 | } elsif ($recctr + 1 == $numrecs) { | |
549 | #This is the last record | |
550 | $rec->data(substr($msgdata, $datadone)); | |
551 | } else { | |
552 | #This is a middle record | |
553 | $rec->data(substr($msgdata, $datadone, length($rec->data))); | |
554 | $datadone += length($rec->data); | |
555 | } | |
556 | $recctr++; | |
557 | } | |
558 | } | |
559 | ||
560 | #To be overridden by sub-classes | |
561 | sub set_message_contents | |
562 | { | |
563 | } | |
564 | ||
565 | #Read only accessors | |
566 | sub server | |
567 | { | |
568 | my $self = shift; | |
569 | return $self->{server}; | |
570 | } | |
571 | ||
572 | #Read/write accessors | |
573 | sub mt | |
574 | { | |
575 | my $self = shift; | |
576 | if (@_) { | |
577 | $self->{mt} = shift; | |
578 | } | |
579 | return $self->{mt}; | |
580 | } | |
581 | sub data | |
582 | { | |
583 | my $self = shift; | |
584 | if (@_) { | |
585 | $self->{data} = shift; | |
586 | } | |
587 | return $self->{data}; | |
588 | } | |
589 | sub records | |
590 | { | |
591 | my $self = shift; | |
592 | if (@_) { | |
593 | $self->{records} = shift; | |
594 | } | |
595 | return $self->{records}; | |
596 | } | |
597 | sub startoffset | |
598 | { | |
599 | my $self = shift; | |
600 | if (@_) { | |
601 | $self->{startoffset} = shift; | |
602 | } | |
603 | return $self->{startoffset}; | |
604 | } | |
605 | sub message_frag_lens | |
606 | { | |
607 | my $self = shift; | |
608 | if (@_) { | |
609 | $self->{message_frag_lens} = shift; | |
610 | } | |
611 | return $self->{message_frag_lens}; | |
612 | } | |
cf7f8592 EK |
613 | sub encoded_length |
614 | { | |
615 | my $self = shift; | |
616 | return TLS_MESSAGE_HEADER_LENGTH + length($self->data); | |
617 | } | |
9effc496 MC |
618 | sub dupext |
619 | { | |
620 | my $self = shift; | |
621 | if (@_) { | |
622 | $self->{dupext} = shift; | |
623 | } | |
624 | return $self->{dupext}; | |
625 | } | |
1c361b4a MC |
626 | sub successondata |
627 | { | |
628 | my $class = shift; | |
629 | if (@_) { | |
630 | $successondata = shift; | |
631 | } | |
632 | return $successondata; | |
633 | } | |
631c1206 | 634 | 1; |