| 
									
										
										
										
											2024-03-20 20:07:54 +08:00
										 |  |  | # Copyright 2016-2024 The OpenSSL Project Authors. All Rights Reserved. | 
					
						
							| 
									
										
										
										
											2015-06-16 20:06:41 +08:00
										 |  |  | # | 
					
						
							| 
									
										
										
										
											2018-12-06 20:03:50 +08:00
										 |  |  | # Licensed under the Apache License 2.0 (the "License").  You may not use | 
					
						
							| 
									
										
										
										
											2016-04-20 22:20:59 +08:00
										 |  |  | # this file except in compliance with the License.  You can obtain a copy | 
					
						
							|  |  |  | # in the file LICENSE in the source distribution or at | 
					
						
							|  |  |  | # https://www.openssl.org/source/license.html | 
					
						
							| 
									
										
										
										
											2015-06-16 20:06:41 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | use strict; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | package TLSProxy::Message; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-08-07 23:22:31 +08:00
										 |  |  | use TLSProxy::Alert; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-01-11 21:18:07 +08:00
										 |  |  | use constant DTLS_MESSAGE_HEADER_LENGTH => 12; | 
					
						
							| 
									
										
										
										
											2015-06-16 20:06:41 +08:00
										 |  |  | use constant TLS_MESSAGE_HEADER_LENGTH => 4; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #Message types | 
					
						
							|  |  |  | use constant { | 
					
						
							|  |  |  |     MT_HELLO_REQUEST => 0, | 
					
						
							|  |  |  |     MT_CLIENT_HELLO => 1, | 
					
						
							|  |  |  |     MT_SERVER_HELLO => 2, | 
					
						
							| 
									
										
										
										
											2024-01-11 21:18:07 +08:00
										 |  |  |     MT_HELLO_VERIFY_REQUEST => 3, | 
					
						
							| 
									
										
										
										
											2015-06-16 20:06:41 +08:00
										 |  |  |     MT_NEW_SESSION_TICKET => 4, | 
					
						
							| 
									
										
										
										
											2016-11-23 23:20:22 +08:00
										 |  |  |     MT_ENCRYPTED_EXTENSIONS => 8, | 
					
						
							| 
									
										
										
										
											2015-06-16 20:06:41 +08:00
										 |  |  |     MT_CERTIFICATE => 11, | 
					
						
							|  |  |  |     MT_SERVER_KEY_EXCHANGE => 12, | 
					
						
							|  |  |  |     MT_CERTIFICATE_REQUEST => 13, | 
					
						
							|  |  |  |     MT_SERVER_HELLO_DONE => 14, | 
					
						
							|  |  |  |     MT_CERTIFICATE_VERIFY => 15, | 
					
						
							|  |  |  |     MT_CLIENT_KEY_EXCHANGE => 16, | 
					
						
							|  |  |  |     MT_FINISHED => 20, | 
					
						
							|  |  |  |     MT_CERTIFICATE_STATUS => 22, | 
					
						
							| 
									
										
										
										
											2021-08-10 04:56:50 +08:00
										 |  |  |     MT_COMPRESSED_CERTIFICATE => 25, | 
					
						
							| 
									
										
										
										
											2015-06-16 20:06:41 +08:00
										 |  |  |     MT_NEXT_PROTO => 67 | 
					
						
							|  |  |  | }; | 
					
						
							| 
									
										
										
										
											2015-08-13 23:58:20 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | #Alert levels | 
					
						
							|  |  |  | use constant { | 
					
						
							|  |  |  |     AL_LEVEL_WARN => 1, | 
					
						
							|  |  |  |     AL_LEVEL_FATAL => 2 | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #Alert descriptions | 
					
						
							|  |  |  | use constant { | 
					
						
							| 
									
										
										
										
											2016-06-21 23:33:52 +08:00
										 |  |  |     AL_DESC_CLOSE_NOTIFY => 0, | 
					
						
							| 
									
										
										
										
											2016-08-03 00:24:54 +08:00
										 |  |  |     AL_DESC_UNEXPECTED_MESSAGE => 10, | 
					
						
							| 
									
										
										
										
											2024-01-11 21:18:07 +08:00
										 |  |  |     AL_DESC_BAD_RECORD_MAC => 20, | 
					
						
							| 
									
										
										
										
											2018-08-08 22:29:33 +08:00
										 |  |  |     AL_DESC_ILLEGAL_PARAMETER => 47, | 
					
						
							| 
									
										
										
										
											2024-08-25 18:08:36 +08:00
										 |  |  |     AL_DESC_DECODE_ERROR => 50, | 
					
						
							| 
									
										
										
										
											2024-01-11 21:18:07 +08:00
										 |  |  |     AL_DESC_PROTOCOL_VERSION => 70, | 
					
						
							| 
									
										
										
										
											2024-08-01 21:57:48 +08:00
										 |  |  |     AL_DESC_NO_RENEGOTIATION => 100, | 
					
						
							|  |  |  |     AL_DESC_MISSING_EXTENSION => 109 | 
					
						
							| 
									
										
										
										
											2015-08-13 23:58:20 +08:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-16 20:06:41 +08:00
										 |  |  | my %message_type = ( | 
					
						
							|  |  |  |     MT_HELLO_REQUEST, "HelloRequest", | 
					
						
							|  |  |  |     MT_CLIENT_HELLO, "ClientHello", | 
					
						
							|  |  |  |     MT_SERVER_HELLO, "ServerHello", | 
					
						
							| 
									
										
										
										
											2024-01-11 21:18:07 +08:00
										 |  |  |     MT_HELLO_VERIFY_REQUEST, "HelloVerifyRequest", | 
					
						
							| 
									
										
										
										
											2015-06-16 20:06:41 +08:00
										 |  |  |     MT_NEW_SESSION_TICKET, "NewSessionTicket", | 
					
						
							| 
									
										
										
										
											2016-11-23 23:20:22 +08:00
										 |  |  |     MT_ENCRYPTED_EXTENSIONS, "EncryptedExtensions", | 
					
						
							| 
									
										
										
										
											2015-06-16 20:06:41 +08:00
										 |  |  |     MT_CERTIFICATE, "Certificate", | 
					
						
							|  |  |  |     MT_SERVER_KEY_EXCHANGE, "ServerKeyExchange", | 
					
						
							|  |  |  |     MT_CERTIFICATE_REQUEST, "CertificateRequest", | 
					
						
							|  |  |  |     MT_SERVER_HELLO_DONE, "ServerHelloDone", | 
					
						
							|  |  |  |     MT_CERTIFICATE_VERIFY, "CertificateVerify", | 
					
						
							|  |  |  |     MT_CLIENT_KEY_EXCHANGE, "ClientKeyExchange", | 
					
						
							|  |  |  |     MT_FINISHED, "Finished", | 
					
						
							|  |  |  |     MT_CERTIFICATE_STATUS, "CertificateStatus", | 
					
						
							| 
									
										
										
										
											2021-08-10 04:56:50 +08:00
										 |  |  |     MT_COMPRESSED_CERTIFICATE, "CompressedCertificate", | 
					
						
							| 
									
										
										
										
											2015-06-16 20:06:41 +08:00
										 |  |  |     MT_NEXT_PROTO, "NextProto" | 
					
						
							|  |  |  | ); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-20 00:24:44 +08:00
										 |  |  | use constant { | 
					
						
							| 
									
										
										
										
											2016-11-29 06:39:23 +08:00
										 |  |  |     EXT_SERVER_NAME => 0, | 
					
						
							| 
									
										
										
										
											2017-11-06 00:46:48 +08:00
										 |  |  |     EXT_MAX_FRAGMENT_LENGTH => 1, | 
					
						
							| 
									
										
										
										
											2016-02-20 00:24:44 +08:00
										 |  |  |     EXT_STATUS_REQUEST => 5, | 
					
						
							| 
									
										
										
										
											2016-11-04 02:51:28 +08:00
										 |  |  |     EXT_SUPPORTED_GROUPS => 10, | 
					
						
							| 
									
										
										
										
											2016-11-29 06:39:23 +08:00
										 |  |  |     EXT_EC_POINT_FORMATS => 11, | 
					
						
							|  |  |  |     EXT_SRP => 12, | 
					
						
							|  |  |  |     EXT_SIG_ALGS => 13, | 
					
						
							|  |  |  |     EXT_USE_SRTP => 14, | 
					
						
							|  |  |  |     EXT_ALPN => 16, | 
					
						
							|  |  |  |     EXT_SCT => 18, | 
					
						
							| 
									
										
										
										
											2021-01-28 03:23:33 +08:00
										 |  |  |     EXT_CLIENT_CERT_TYPE => 19, | 
					
						
							|  |  |  |     EXT_SERVER_CERT_TYPE => 20, | 
					
						
							| 
									
										
										
										
											2016-11-29 06:39:23 +08:00
										 |  |  |     EXT_PADDING => 21, | 
					
						
							| 
									
										
										
										
											2016-02-20 00:24:44 +08:00
										 |  |  |     EXT_ENCRYPT_THEN_MAC => 22, | 
					
						
							|  |  |  |     EXT_EXTENDED_MASTER_SECRET => 23, | 
					
						
							| 
									
										
										
										
											2021-08-10 04:56:50 +08:00
										 |  |  |     EXT_COMPRESS_CERTIFICATE => 27, | 
					
						
							| 
									
										
										
										
											2016-02-20 00:24:44 +08:00
										 |  |  |     EXT_SESSION_TICKET => 35, | 
					
						
							| 
									
										
										
										
											2018-01-12 00:55:05 +08:00
										 |  |  |     EXT_KEY_SHARE => 51, | 
					
						
							| 
									
										
										
										
											2017-01-20 20:08:51 +08:00
										 |  |  |     EXT_PSK => 41, | 
					
						
							| 
									
										
										
										
											2016-11-29 06:39:23 +08:00
										 |  |  |     EXT_SUPPORTED_VERSIONS => 43, | 
					
						
							| 
									
										
										
										
											2017-03-03 18:28:02 +08:00
										 |  |  |     EXT_COOKIE => 44, | 
					
						
							| 
									
										
										
										
											2017-01-12 23:28:48 +08:00
										 |  |  |     EXT_PSK_KEX_MODES => 45, | 
					
						
							| 
									
										
											  
											
												Add TLSv1.3 post-handshake authentication (PHA)
Add SSL_verify_client_post_handshake() for servers to initiate PHA
Add SSL_force_post_handshake_auth() for clients that don't have certificates
initially configured, but use a certificate callback.
Update SSL_CTX_set_verify()/SSL_set_verify() mode:
* Add SSL_VERIFY_POST_HANDSHAKE to postpone client authentication until after
the initial handshake.
* Update SSL_VERIFY_CLIENT_ONCE now only sends out one CertRequest regardless
of when the certificate authentication takes place; either initial handshake,
re-negotiation, or post-handshake authentication.
Add 'RequestPostHandshake' and 'RequirePostHandshake' SSL_CONF options that
add the SSL_VERIFY_POST_HANDSHAKE to the 'Request' and 'Require' options
Add support to s_client:
* Enabled automatically when cert is configured
* Can be forced enabled via -force_pha
Add support to s_server:
* Use 'c' to invoke PHA in s_server
* Remove some dead code
Update documentation
Update unit tests:
* Illegal use of PHA extension
* TLSv1.3 certificate tests
DTLS and TLS behave ever-so-slightly differently. So, when DTLS1.3 is
implemented, it's PHA support state machine may need to be different.
Add a TODO and a #error
Update handshake context to deal with PHA.
The handshake context for TLSv1.3 post-handshake auth is up through the
ClientFinish message, plus the CertificateRequest message. Subsequent
Certificate, CertificateVerify, and Finish messages are based on this
handshake context (not the Certificate message per se, but it's included
after the hash). KeyUpdate, NewSessionTicket, and prior Certificate
Request messages are not included in post-handshake authentication.
After the ClientFinished message is processed, save off the digest state
for future post-handshake authentication. When post-handshake auth occurs,
copy over the saved handshake context into the "main" handshake digest.
This effectively discards the any KeyUpdate or NewSessionTicket messages
and any prior post-handshake authentication.
This, of course, assumes that the ID-22 did not mean to include any
previous post-handshake authentication into the new handshake transcript.
This is implied by section 4.4.1 that lists messages only up to the
first ClientFinished.
Reviewed-by: Ben Kaduk <kaduk@mit.edu>
Reviewed-by: Matt Caswell <matt@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/4964)
											
										 
											2017-12-19 05:52:28 +08:00
										 |  |  |     EXT_POST_HANDSHAKE_AUTH => 49, | 
					
						
							| 
									
										
										
										
											2018-01-25 04:45:08 +08:00
										 |  |  |     EXT_SIG_ALGS_CERT => 50, | 
					
						
							| 
									
										
										
										
											2016-11-29 06:39:23 +08:00
										 |  |  |     EXT_RENEGOTIATE => 65281, | 
					
						
							|  |  |  |     EXT_NPN => 13172, | 
					
						
							| 
									
										
										
										
											2019-01-05 00:55:15 +08:00
										 |  |  |     EXT_CRYPTOPRO_BUG_EXTENSION => 0xfde8, | 
					
						
							| 
									
										
										
										
											2017-05-08 23:05:49 +08:00
										 |  |  |     EXT_UNKNOWN => 0xfffe, | 
					
						
							| 
									
										
										
										
											2017-03-10 21:54:32 +08:00
										 |  |  |     #Unknown extension that should appear last | 
					
						
							|  |  |  |     EXT_FORCE_LAST => 0xffff | 
					
						
							| 
									
										
										
										
											2016-02-20 00:24:44 +08:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-18 23:05:49 +08:00
										 |  |  | # SignatureScheme of TLS 1.3 from: | 
					
						
							|  |  |  | # https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-signaturescheme | 
					
						
							| 
									
										
										
										
											2017-04-27 22:46:07 +08:00
										 |  |  | # We have to manually grab the SHA224 equivalents from the old registry | 
					
						
							|  |  |  | use constant { | 
					
						
							|  |  |  |     SIG_ALG_RSA_PKCS1_SHA256 => 0x0401, | 
					
						
							|  |  |  |     SIG_ALG_RSA_PKCS1_SHA384 => 0x0501, | 
					
						
							|  |  |  |     SIG_ALG_RSA_PKCS1_SHA512 => 0x0601, | 
					
						
							|  |  |  |     SIG_ALG_ECDSA_SECP256R1_SHA256 => 0x0403, | 
					
						
							|  |  |  |     SIG_ALG_ECDSA_SECP384R1_SHA384 => 0x0503, | 
					
						
							|  |  |  |     SIG_ALG_ECDSA_SECP521R1_SHA512 => 0x0603, | 
					
						
							| 
									
										
										
										
											2018-07-18 00:29:08 +08:00
										 |  |  |     SIG_ALG_RSA_PSS_RSAE_SHA256 => 0x0804, | 
					
						
							|  |  |  |     SIG_ALG_RSA_PSS_RSAE_SHA384 => 0x0805, | 
					
						
							|  |  |  |     SIG_ALG_RSA_PSS_RSAE_SHA512 => 0x0806, | 
					
						
							| 
									
										
										
										
											2017-04-27 22:46:07 +08:00
										 |  |  |     SIG_ALG_ED25519 => 0x0807, | 
					
						
							|  |  |  |     SIG_ALG_ED448 => 0x0808, | 
					
						
							| 
									
										
										
										
											2018-07-18 00:29:08 +08:00
										 |  |  |     SIG_ALG_RSA_PSS_PSS_SHA256 => 0x0809, | 
					
						
							|  |  |  |     SIG_ALG_RSA_PSS_PSS_SHA384 => 0x080a, | 
					
						
							|  |  |  |     SIG_ALG_RSA_PSS_PSS_SHA512 => 0x080b, | 
					
						
							| 
									
										
										
										
											2017-04-27 22:46:07 +08:00
										 |  |  |     SIG_ALG_RSA_PKCS1_SHA1 => 0x0201, | 
					
						
							|  |  |  |     SIG_ALG_ECDSA_SHA1 => 0x0203, | 
					
						
							|  |  |  |     SIG_ALG_DSA_SHA1 => 0x0202, | 
					
						
							|  |  |  |     SIG_ALG_DSA_SHA256 => 0x0402, | 
					
						
							|  |  |  |     SIG_ALG_DSA_SHA384 => 0x0502, | 
					
						
							|  |  |  |     SIG_ALG_DSA_SHA512 => 0x0602, | 
					
						
							|  |  |  |     OSSL_SIG_ALG_RSA_PKCS1_SHA224 => 0x0301, | 
					
						
							|  |  |  |     OSSL_SIG_ALG_DSA_SHA224 => 0x0302, | 
					
						
							|  |  |  |     OSSL_SIG_ALG_ECDSA_SHA224 => 0x0303 | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-28 23:01:57 +08:00
										 |  |  | use constant { | 
					
						
							| 
									
										
										
										
											2018-08-08 22:29:33 +08:00
										 |  |  |     CIPHER_RSA_WITH_AES_128_CBC_SHA => 0x002f, | 
					
						
							| 
									
										
										
										
											2017-01-05 20:32:06 +08:00
										 |  |  |     CIPHER_DHE_RSA_AES_128_SHA => 0x0033, | 
					
						
							| 
									
										
										
										
											2017-03-16 04:35:23 +08:00
										 |  |  |     CIPHER_ADH_AES_128_SHA => 0x0034, | 
					
						
							|  |  |  |     CIPHER_TLS13_AES_128_GCM_SHA256 => 0x1301, | 
					
						
							|  |  |  |     CIPHER_TLS13_AES_256_GCM_SHA384 => 0x1302 | 
					
						
							| 
									
										
										
										
											2016-12-28 23:01:57 +08:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-09-05 23:21:56 +08:00
										 |  |  | use constant { | 
					
						
							|  |  |  |     CLIENT => 0, | 
					
						
							|  |  |  |     SERVER => 1 | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-16 20:06:41 +08:00
										 |  |  | my $payload = ""; | 
					
						
							|  |  |  | my $messlen = -1; | 
					
						
							|  |  |  | my $mt; | 
					
						
							|  |  |  | my $startoffset = -1; | 
					
						
							|  |  |  | my $server = 0; | 
					
						
							|  |  |  | my $success = 0; | 
					
						
							|  |  |  | my $end = 0; | 
					
						
							|  |  |  | my @message_rec_list = (); | 
					
						
							|  |  |  | my @message_frag_lens = (); | 
					
						
							| 
									
										
										
										
											2015-08-07 21:38:21 +08:00
										 |  |  | my $ciphersuite = 0; | 
					
						
							| 
									
										
										
										
											2017-01-20 20:08:51 +08:00
										 |  |  | my $successondata = 0; | 
					
						
							| 
									
										
										
										
											2018-08-07 23:22:31 +08:00
										 |  |  | my $alert; | 
					
						
							| 
									
										
										
										
											2015-06-16 20:06:41 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | sub clear | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     $payload = ""; | 
					
						
							|  |  |  |     $messlen = -1; | 
					
						
							|  |  |  |     $startoffset = -1; | 
					
						
							|  |  |  |     $server = 0; | 
					
						
							|  |  |  |     $success = 0; | 
					
						
							|  |  |  |     $end = 0; | 
					
						
							| 
									
										
										
										
											2017-01-20 20:08:51 +08:00
										 |  |  |     $successondata = 0; | 
					
						
							| 
									
										
										
										
											2015-06-16 20:06:41 +08:00
										 |  |  |     @message_rec_list = (); | 
					
						
							|  |  |  |     @message_frag_lens = (); | 
					
						
							| 
									
										
										
										
											2018-08-07 23:22:31 +08:00
										 |  |  |     $alert = undef; | 
					
						
							| 
									
										
										
										
											2015-06-16 20:06:41 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #Class method to extract messages from a record | 
					
						
							|  |  |  | sub get_messages | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     my $class = shift; | 
					
						
							|  |  |  |     my $serverin = shift; | 
					
						
							|  |  |  |     my $record = shift; | 
					
						
							| 
									
										
										
										
											2024-01-11 21:18:07 +08:00
										 |  |  |     my $isdtls = shift; | 
					
						
							| 
									
										
										
										
											2015-06-16 20:06:41 +08:00
										 |  |  |     my @messages = (); | 
					
						
							|  |  |  |     my $message; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-08-07 21:38:21 +08:00
										 |  |  |     @message_frag_lens = (); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-16 20:06:41 +08:00
										 |  |  |     if ($serverin != $server && length($payload) != 0) { | 
					
						
							|  |  |  |         die "Changed peer, but we still have fragment data\n"; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     $server = $serverin; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if ($record->content_type == TLSProxy::Record::RT_CCS) { | 
					
						
							|  |  |  |         if ($payload ne "") { | 
					
						
							|  |  |  |             #We can't handle this yet | 
					
						
							|  |  |  |             die "CCS received before message data complete\n"; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2017-11-13 22:40:46 +08:00
										 |  |  |         if (!TLSProxy::Proxy->is_tls13()) { | 
					
						
							|  |  |  |             if ($server) { | 
					
						
							|  |  |  |                 TLSProxy::Record->server_encrypting(1); | 
					
						
							|  |  |  |             } else { | 
					
						
							|  |  |  |                 TLSProxy::Record->client_encrypting(1); | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2015-06-16 20:06:41 +08:00
										 |  |  |         } | 
					
						
							|  |  |  |     } elsif ($record->content_type == TLSProxy::Record::RT_HANDSHAKE) { | 
					
						
							|  |  |  |         if ($record->len == 0 || $record->len_real == 0) { | 
					
						
							|  |  |  |             print "  Message truncated\n"; | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |             my $recoffset = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if (length $payload > 0) { | 
					
						
							|  |  |  |                 #We are continuing processing a message started in a previous | 
					
						
							|  |  |  |                 #record. Add this record to the list associated with this | 
					
						
							|  |  |  |                 #message | 
					
						
							|  |  |  |                 push @message_rec_list, $record; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 if ($messlen <= length($payload)) { | 
					
						
							|  |  |  |                     #Shouldn't happen | 
					
						
							|  |  |  |                     die "Internal error: invalid messlen: ".$messlen | 
					
						
							|  |  |  |                         ." payload length:".length($payload)."\n"; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |                 if (length($payload) + $record->decrypt_len >= $messlen) { | 
					
						
							|  |  |  |                     #We can complete the message with this record | 
					
						
							|  |  |  |                     $recoffset = $messlen - length($payload); | 
					
						
							|  |  |  |                     $payload .= substr($record->decrypt_data, 0, $recoffset); | 
					
						
							|  |  |  |                     push @message_frag_lens, $recoffset; | 
					
						
							| 
									
										
										
										
											2024-01-11 21:18:07 +08:00
										 |  |  |                     if ($isdtls) { | 
					
						
							|  |  |  |                         # We must set $msgseq, $msgfrag, $msgfragoffs | 
					
						
							|  |  |  |                         die "Internal error: cannot handle partial dtls messages\n" | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  |                     $message = create_message($server, $mt, | 
					
						
							|  |  |  |                         #$msgseq, $msgfrag, $msgfragoffs, | 
					
						
							|  |  |  |                         0, 0, 0, | 
					
						
							|  |  |  |                         $payload, $startoffset, $isdtls); | 
					
						
							| 
									
										
										
										
											2015-06-16 20:06:41 +08:00
										 |  |  |                     push @messages, $message; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                     $payload = ""; | 
					
						
							|  |  |  |                 } else { | 
					
						
							|  |  |  |                     #This is just part of the total message | 
					
						
							|  |  |  |                     $payload .= $record->decrypt_data; | 
					
						
							|  |  |  |                     $recoffset = $record->decrypt_len; | 
					
						
							|  |  |  |                     push @message_frag_lens, $record->decrypt_len; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |                 print "  Partial message data read: ".$recoffset." bytes\n"; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             while ($record->decrypt_len > $recoffset) { | 
					
						
							|  |  |  |                 #We are at the start of a new message | 
					
						
							| 
									
										
										
										
											2024-01-11 21:18:07 +08:00
										 |  |  |                 my $msgheaderlen = $isdtls ? DTLS_MESSAGE_HEADER_LENGTH | 
					
						
							|  |  |  |                                            : TLS_MESSAGE_HEADER_LENGTH; | 
					
						
							|  |  |  |                 if ($record->decrypt_len - $recoffset < $msgheaderlen) { | 
					
						
							| 
									
										
										
										
											2015-06-16 20:06:41 +08:00
										 |  |  |                     #Whilst technically probably valid we can't cope with this | 
					
						
							|  |  |  |                     die "End of record in the middle of a message header\n"; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |                 @message_rec_list = ($record); | 
					
						
							|  |  |  |                 my $lenhi; | 
					
						
							|  |  |  |                 my $lenlo; | 
					
						
							| 
									
										
										
										
											2024-01-11 21:18:07 +08:00
										 |  |  |                 my $msgseq; | 
					
						
							|  |  |  |                 my $msgfrag; | 
					
						
							|  |  |  |                 my $msgfragoffs; | 
					
						
							|  |  |  |                 if ($isdtls) { | 
					
						
							|  |  |  |                     my $msgfraghi; | 
					
						
							|  |  |  |                     my $msgfraglo; | 
					
						
							|  |  |  |                     my $msgfragoffshi; | 
					
						
							|  |  |  |                     my $msgfragoffslo; | 
					
						
							|  |  |  |                     ($mt, $lenhi, $lenlo, $msgseq, $msgfraghi, $msgfraglo, $msgfragoffshi, $msgfragoffslo) = | 
					
						
							|  |  |  |                         unpack('CnCnnCnC', substr($record->decrypt_data, $recoffset)); | 
					
						
							|  |  |  |                     $msgfrag = ($msgfraghi << 8) | $msgfraglo; | 
					
						
							|  |  |  |                     $msgfragoffs = ($msgfragoffshi << 8) | $msgfragoffslo; | 
					
						
							|  |  |  |                 } else { | 
					
						
							|  |  |  |                     ($mt, $lenhi, $lenlo) = | 
					
						
							|  |  |  |                         unpack('CnC', substr($record->decrypt_data, $recoffset)); | 
					
						
							|  |  |  |                 } | 
					
						
							| 
									
										
										
										
											2015-06-16 20:06:41 +08:00
										 |  |  |                 $messlen = ($lenhi << 8) | $lenlo; | 
					
						
							| 
									
										
										
										
											2024-01-11 21:18:07 +08:00
										 |  |  |                 print "  Message type: $message_type{$mt}($mt)\n"; | 
					
						
							| 
									
										
										
										
											2015-06-16 20:06:41 +08:00
										 |  |  |                 print "  Message Length: $messlen\n"; | 
					
						
							|  |  |  |                 $startoffset = $recoffset; | 
					
						
							| 
									
										
										
										
											2024-01-11 21:18:07 +08:00
										 |  |  |                 $recoffset += $msgheaderlen; | 
					
						
							| 
									
										
										
										
											2015-06-16 20:06:41 +08:00
										 |  |  |                 $payload = ""; | 
					
						
							| 
									
										
										
										
											2019-02-01 01:55:30 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-11-23 00:16:23 +08:00
										 |  |  |                 if ($recoffset <= $record->decrypt_len) { | 
					
						
							| 
									
										
										
										
											2015-06-16 20:06:41 +08:00
										 |  |  |                     #Some payload data is present in this record | 
					
						
							|  |  |  |                     if ($record->decrypt_len - $recoffset >= $messlen) { | 
					
						
							|  |  |  |                         #We can complete the message with this record | 
					
						
							|  |  |  |                         $payload .= substr($record->decrypt_data, $recoffset, | 
					
						
							|  |  |  |                                            $messlen); | 
					
						
							|  |  |  |                         $recoffset += $messlen; | 
					
						
							|  |  |  |                         push @message_frag_lens, $messlen; | 
					
						
							| 
									
										
										
										
											2024-01-11 21:18:07 +08:00
										 |  |  |                         $message = create_message($server, $mt, $msgseq, | 
					
						
							|  |  |  |                                                   $msgfrag, $msgfragoffs, | 
					
						
							|  |  |  |                                                   $payload, $startoffset, $isdtls); | 
					
						
							| 
									
										
										
										
											2015-06-16 20:06:41 +08:00
										 |  |  |                         push @messages, $message; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                         $payload = ""; | 
					
						
							|  |  |  |                     } else { | 
					
						
							|  |  |  |                         #This is just part of the total message | 
					
						
							|  |  |  |                         $payload .= substr($record->decrypt_data, $recoffset, | 
					
						
							|  |  |  |                                            $record->decrypt_len - $recoffset); | 
					
						
							|  |  |  |                         $recoffset = $record->decrypt_len; | 
					
						
							|  |  |  |                         push @message_frag_lens, $recoffset; | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } elsif ($record->content_type == TLSProxy::Record::RT_APPLICATION_DATA) { | 
					
						
							|  |  |  |         print "  [ENCRYPTED APPLICATION DATA]\n"; | 
					
						
							|  |  |  |         print "  [".$record->decrypt_data."]\n"; | 
					
						
							| 
									
										
										
										
											2017-01-20 20:08:51 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |         if ($successondata) { | 
					
						
							|  |  |  |             $success = 1; | 
					
						
							|  |  |  |             $end = 1; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2015-06-16 20:06:41 +08:00
										 |  |  |     } elsif ($record->content_type == TLSProxy::Record::RT_ALERT) { | 
					
						
							| 
									
										
										
										
											2015-08-13 23:58:20 +08:00
										 |  |  |         my ($alertlev, $alertdesc) = unpack('CC', $record->decrypt_data); | 
					
						
							| 
									
										
										
										
											2018-04-16 20:10:39 +08:00
										 |  |  |         print "  [$alertlev, $alertdesc]\n"; | 
					
						
							| 
									
										
										
										
											2015-08-13 23:58:20 +08:00
										 |  |  |         #A CloseNotify from the client indicates we have finished successfully | 
					
						
							|  |  |  |         #(we assume) | 
					
						
							| 
									
										
										
										
											2016-08-10 12:45:51 +08:00
										 |  |  |         if (!$end && !$server && $alertlev == AL_LEVEL_WARN | 
					
						
							| 
									
										
										
										
											2015-08-13 23:58:20 +08:00
										 |  |  |             && $alertdesc == AL_DESC_CLOSE_NOTIFY) { | 
					
						
							|  |  |  |             $success = 1; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2018-04-16 20:10:39 +08:00
										 |  |  |         #Fatal or close notify alerts end the test | 
					
						
							|  |  |  |         if ($alertlev == AL_LEVEL_FATAL || $alertdesc == AL_DESC_CLOSE_NOTIFY) { | 
					
						
							|  |  |  |             $end = 1; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2018-08-07 23:22:31 +08:00
										 |  |  |         $alert = TLSProxy::Alert->new( | 
					
						
							|  |  |  |             $server, | 
					
						
							|  |  |  |             $record->encrypted, | 
					
						
							|  |  |  |             $alertlev, | 
					
						
							|  |  |  |             $alertdesc); | 
					
						
							| 
									
										
										
										
											2015-06-16 20:06:41 +08:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return @messages; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #Function to work out which sub-class we need to create and then | 
					
						
							|  |  |  | #construct it | 
					
						
							|  |  |  | sub create_message | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2024-01-11 21:18:07 +08:00
										 |  |  |     my ($server, $mt, $msgseq, $msgfrag, $msgfragoffs, $data, $startoffset, $isdtls) = @_; | 
					
						
							| 
									
										
										
										
											2015-06-16 20:06:41 +08:00
										 |  |  |     my $message; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if ($mt == MT_CLIENT_HELLO) { | 
					
						
							|  |  |  |         $message = TLSProxy::ClientHello->new( | 
					
						
							| 
									
										
										
										
											2024-01-11 21:18:07 +08:00
										 |  |  |             $isdtls, | 
					
						
							| 
									
										
										
										
											2015-06-16 20:06:41 +08:00
										 |  |  |             $server, | 
					
						
							| 
									
										
										
										
											2024-01-11 21:18:07 +08:00
										 |  |  |             $msgseq, | 
					
						
							|  |  |  |             $msgfrag, | 
					
						
							|  |  |  |             $msgfragoffs, | 
					
						
							| 
									
										
										
										
											2015-06-16 20:06:41 +08:00
										 |  |  |             $data, | 
					
						
							|  |  |  |             [@message_rec_list], | 
					
						
							|  |  |  |             $startoffset, | 
					
						
							|  |  |  |             [@message_frag_lens] | 
					
						
							|  |  |  |         ); | 
					
						
							|  |  |  |         $message->parse(); | 
					
						
							| 
									
										
										
										
											2015-08-07 21:38:21 +08:00
										 |  |  |     } elsif ($mt == MT_SERVER_HELLO) { | 
					
						
							|  |  |  |         $message = TLSProxy::ServerHello->new( | 
					
						
							| 
									
										
										
										
											2024-01-11 21:18:07 +08:00
										 |  |  |             $isdtls, | 
					
						
							|  |  |  |             $server, | 
					
						
							|  |  |  |             $msgseq, | 
					
						
							|  |  |  |             $msgfrag, | 
					
						
							|  |  |  |             $msgfragoffs, | 
					
						
							|  |  |  |             $data, | 
					
						
							|  |  |  |             [@message_rec_list], | 
					
						
							|  |  |  |             $startoffset, | 
					
						
							|  |  |  |             [@message_frag_lens] | 
					
						
							|  |  |  |         ); | 
					
						
							|  |  |  |         $message->parse(); | 
					
						
							|  |  |  |     } elsif ($mt == MT_HELLO_VERIFY_REQUEST) { | 
					
						
							|  |  |  |         $message = TLSProxy::HelloVerifyRequest->new( | 
					
						
							|  |  |  |             $isdtls, | 
					
						
							| 
									
										
										
										
											2015-08-07 21:38:21 +08:00
										 |  |  |             $server, | 
					
						
							| 
									
										
										
										
											2024-01-11 21:18:07 +08:00
										 |  |  |             $msgseq, | 
					
						
							|  |  |  |             $msgfrag, | 
					
						
							|  |  |  |             $msgfragoffs, | 
					
						
							| 
									
										
										
										
											2015-08-07 21:38:21 +08:00
										 |  |  |             $data, | 
					
						
							|  |  |  |             [@message_rec_list], | 
					
						
							|  |  |  |             $startoffset, | 
					
						
							|  |  |  |             [@message_frag_lens] | 
					
						
							|  |  |  |         ); | 
					
						
							| 
									
										
										
										
											2016-11-29 06:39:23 +08:00
										 |  |  |         $message->parse(); | 
					
						
							|  |  |  |     } elsif ($mt == MT_ENCRYPTED_EXTENSIONS) { | 
					
						
							|  |  |  |         $message = TLSProxy::EncryptedExtensions->new( | 
					
						
							| 
									
										
										
										
											2024-01-11 21:18:07 +08:00
										 |  |  |             $isdtls, | 
					
						
							| 
									
										
										
										
											2016-11-29 06:39:23 +08:00
										 |  |  |             $server, | 
					
						
							| 
									
										
										
										
											2024-01-11 21:18:07 +08:00
										 |  |  |             $msgseq, | 
					
						
							|  |  |  |             $msgfrag, | 
					
						
							|  |  |  |             $msgfragoffs, | 
					
						
							| 
									
										
										
										
											2016-11-29 06:39:23 +08:00
										 |  |  |             $data, | 
					
						
							|  |  |  |             [@message_rec_list], | 
					
						
							|  |  |  |             $startoffset, | 
					
						
							|  |  |  |             [@message_frag_lens] | 
					
						
							|  |  |  |         ); | 
					
						
							| 
									
										
										
										
											2016-12-02 17:14:15 +08:00
										 |  |  |         $message->parse(); | 
					
						
							|  |  |  |     } elsif ($mt == MT_CERTIFICATE) { | 
					
						
							|  |  |  |         $message = TLSProxy::Certificate->new( | 
					
						
							| 
									
										
										
										
											2024-01-11 21:18:07 +08:00
										 |  |  |             $isdtls, | 
					
						
							| 
									
										
										
										
											2016-12-02 17:14:15 +08:00
										 |  |  |             $server, | 
					
						
							| 
									
										
										
										
											2024-01-11 21:18:07 +08:00
										 |  |  |             $msgseq, | 
					
						
							|  |  |  |             $msgfrag, | 
					
						
							|  |  |  |             $msgfragoffs, | 
					
						
							| 
									
										
										
										
											2016-12-02 17:14:15 +08:00
										 |  |  |             $data, | 
					
						
							|  |  |  |             [@message_rec_list], | 
					
						
							|  |  |  |             $startoffset, | 
					
						
							|  |  |  |             [@message_frag_lens] | 
					
						
							|  |  |  |         ); | 
					
						
							| 
									
										
										
										
											2017-01-05 20:28:40 +08:00
										 |  |  |         $message->parse(); | 
					
						
							| 
									
										
										
										
											2019-09-05 23:21:56 +08:00
										 |  |  |     } elsif ($mt == MT_CERTIFICATE_REQUEST) { | 
					
						
							|  |  |  |         $message = TLSProxy::CertificateRequest->new( | 
					
						
							| 
									
										
										
										
											2024-01-11 21:18:07 +08:00
										 |  |  |             $isdtls, | 
					
						
							| 
									
										
										
										
											2019-09-05 23:21:56 +08:00
										 |  |  |             $server, | 
					
						
							| 
									
										
										
										
											2024-01-11 21:18:07 +08:00
										 |  |  |             $msgseq, | 
					
						
							|  |  |  |             $msgfrag, | 
					
						
							|  |  |  |             $msgfragoffs, | 
					
						
							| 
									
										
										
										
											2019-09-05 23:21:56 +08:00
										 |  |  |             $data, | 
					
						
							|  |  |  |             [@message_rec_list], | 
					
						
							|  |  |  |             $startoffset, | 
					
						
							|  |  |  |             [@message_frag_lens] | 
					
						
							|  |  |  |         ); | 
					
						
							|  |  |  |         $message->parse(); | 
					
						
							| 
									
										
										
										
											2017-01-05 20:28:40 +08:00
										 |  |  |     } elsif ($mt == MT_CERTIFICATE_VERIFY) { | 
					
						
							|  |  |  |         $message = TLSProxy::CertificateVerify->new( | 
					
						
							| 
									
										
										
										
											2024-01-11 21:18:07 +08:00
										 |  |  |             $isdtls, | 
					
						
							| 
									
										
										
										
											2017-01-05 20:28:40 +08:00
										 |  |  |             $server, | 
					
						
							| 
									
										
										
										
											2024-01-11 21:18:07 +08:00
										 |  |  |             $msgseq, | 
					
						
							|  |  |  |             $msgfrag, | 
					
						
							|  |  |  |             $msgfragoffs, | 
					
						
							| 
									
										
										
										
											2017-01-05 20:28:40 +08:00
										 |  |  |             $data, | 
					
						
							|  |  |  |             [@message_rec_list], | 
					
						
							|  |  |  |             $startoffset, | 
					
						
							|  |  |  |             [@message_frag_lens] | 
					
						
							|  |  |  |         ); | 
					
						
							| 
									
										
										
										
											2015-08-07 21:38:21 +08:00
										 |  |  |         $message->parse(); | 
					
						
							|  |  |  |     } elsif ($mt == MT_SERVER_KEY_EXCHANGE) { | 
					
						
							|  |  |  |         $message = TLSProxy::ServerKeyExchange->new( | 
					
						
							| 
									
										
										
										
											2024-01-11 21:18:07 +08:00
										 |  |  |             $isdtls, | 
					
						
							| 
									
										
										
										
											2015-08-07 21:38:21 +08:00
										 |  |  |             $server, | 
					
						
							| 
									
										
										
										
											2024-01-11 21:18:07 +08:00
										 |  |  |             $msgseq, | 
					
						
							|  |  |  |             $msgfrag, | 
					
						
							|  |  |  |             $msgfragoffs, | 
					
						
							| 
									
										
										
										
											2015-08-07 21:38:21 +08:00
										 |  |  |             $data, | 
					
						
							|  |  |  |             [@message_rec_list], | 
					
						
							|  |  |  |             $startoffset, | 
					
						
							|  |  |  |             [@message_frag_lens] | 
					
						
							| 
									
										
										
										
											2015-09-15 18:06:12 +08:00
										 |  |  |         ); | 
					
						
							|  |  |  |         $message->parse(); | 
					
						
							|  |  |  |     } elsif ($mt == MT_NEW_SESSION_TICKET) { | 
					
						
							| 
									
										
										
										
											2024-01-11 21:18:07 +08:00
										 |  |  |         if ($isdtls) { | 
					
						
							|  |  |  |             $message = TLSProxy::NewSessionTicket->new_dtls( | 
					
						
							|  |  |  |                 $server, | 
					
						
							|  |  |  |                 $msgseq, | 
					
						
							|  |  |  |                 $msgfrag, | 
					
						
							|  |  |  |                 $msgfragoffs, | 
					
						
							|  |  |  |                 $data, | 
					
						
							|  |  |  |                 [@message_rec_list], | 
					
						
							|  |  |  |                 $startoffset, | 
					
						
							|  |  |  |                 [@message_frag_lens] | 
					
						
							|  |  |  |             ); | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |             $message = TLSProxy::NewSessionTicket->new( | 
					
						
							|  |  |  |                 $server, | 
					
						
							|  |  |  |                 $data, | 
					
						
							|  |  |  |                 [@message_rec_list], | 
					
						
							|  |  |  |                 $startoffset, | 
					
						
							|  |  |  |                 [@message_frag_lens] | 
					
						
							|  |  |  |             ); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2015-08-07 21:38:21 +08:00
										 |  |  |         $message->parse(); | 
					
						
							| 
									
										
										
										
											2024-06-21 21:29:26 +08:00
										 |  |  |     }  elsif ($mt == MT_NEXT_PROTO) { | 
					
						
							|  |  |  |         $message = TLSProxy::NextProto->new( | 
					
						
							|  |  |  |             $isdtls, | 
					
						
							|  |  |  |             $server, | 
					
						
							|  |  |  |             $msgseq, | 
					
						
							|  |  |  |             $msgfrag, | 
					
						
							|  |  |  |             $msgfragoffs, | 
					
						
							|  |  |  |             $data, | 
					
						
							|  |  |  |             [@message_rec_list], | 
					
						
							|  |  |  |             $startoffset, | 
					
						
							|  |  |  |             [@message_frag_lens] | 
					
						
							|  |  |  |         ); | 
					
						
							|  |  |  |         $message->parse(); | 
					
						
							| 
									
										
										
										
											2015-06-16 20:06:41 +08:00
										 |  |  |     } else { | 
					
						
							|  |  |  |         #Unknown message type | 
					
						
							|  |  |  |         $message = TLSProxy::Message->new( | 
					
						
							| 
									
										
										
										
											2024-01-11 21:18:07 +08:00
										 |  |  |             $isdtls, | 
					
						
							| 
									
										
										
										
											2015-06-16 20:06:41 +08:00
										 |  |  |             $server, | 
					
						
							|  |  |  |             $mt, | 
					
						
							| 
									
										
										
										
											2024-01-11 21:18:07 +08:00
										 |  |  |             $msgseq, | 
					
						
							|  |  |  |             $msgfrag, | 
					
						
							|  |  |  |             $msgfragoffs, | 
					
						
							| 
									
										
										
										
											2015-06-16 20:06:41 +08:00
										 |  |  |             $data, | 
					
						
							|  |  |  |             [@message_rec_list], | 
					
						
							|  |  |  |             $startoffset, | 
					
						
							|  |  |  |             [@message_frag_lens] | 
					
						
							|  |  |  |         ); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return $message; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | sub end | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     my $class = shift; | 
					
						
							|  |  |  |     return $end; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | sub success | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     my $class = shift; | 
					
						
							|  |  |  |     return $success; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2015-08-07 21:38:21 +08:00
										 |  |  | sub fail | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     my $class = shift; | 
					
						
							|  |  |  |     return !$success && $end; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2018-08-07 23:22:31 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | sub alert | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return $alert; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-16 20:06:41 +08:00
										 |  |  | sub new | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     my $class = shift; | 
					
						
							| 
									
										
										
										
											2024-01-11 21:18:07 +08:00
										 |  |  |     my ($isdtls, | 
					
						
							|  |  |  |         $server, | 
					
						
							| 
									
										
										
										
											2015-06-16 20:06:41 +08:00
										 |  |  |         $mt, | 
					
						
							| 
									
										
										
										
											2024-01-11 21:18:07 +08:00
										 |  |  |         $msgseq, | 
					
						
							|  |  |  |         $msgfrag, | 
					
						
							|  |  |  |         $msgfragoffs, | 
					
						
							| 
									
										
										
										
											2015-06-16 20:06:41 +08:00
										 |  |  |         $data, | 
					
						
							|  |  |  |         $records, | 
					
						
							|  |  |  |         $startoffset, | 
					
						
							|  |  |  |         $message_frag_lens) = @_; | 
					
						
							| 
									
										
										
										
											2019-02-01 01:55:30 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-16 20:06:41 +08:00
										 |  |  |     my $self = { | 
					
						
							| 
									
										
										
										
											2024-01-11 21:18:07 +08:00
										 |  |  |         isdtls => $isdtls, | 
					
						
							| 
									
										
										
										
											2015-06-16 20:06:41 +08:00
										 |  |  |         server => $server, | 
					
						
							|  |  |  |         data => $data, | 
					
						
							|  |  |  |         records => $records, | 
					
						
							|  |  |  |         mt => $mt, | 
					
						
							| 
									
										
										
										
											2024-01-11 21:18:07 +08:00
										 |  |  |         msgseq => $msgseq, | 
					
						
							|  |  |  |         msgfrag => $msgfrag, | 
					
						
							|  |  |  |         msgfragoffs => $msgfragoffs, | 
					
						
							| 
									
										
										
										
											2015-06-16 20:06:41 +08:00
										 |  |  |         startoffset => $startoffset, | 
					
						
							| 
									
										
										
										
											2019-01-05 00:55:15 +08:00
										 |  |  |         message_frag_lens => $message_frag_lens, | 
					
						
							|  |  |  |         dupext => -1 | 
					
						
							| 
									
										
										
										
											2015-06-16 20:06:41 +08:00
										 |  |  |     }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return bless $self, $class; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-08-07 21:38:21 +08:00
										 |  |  | sub ciphersuite | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     my $class = shift; | 
					
						
							|  |  |  |     if (@_) { | 
					
						
							|  |  |  |       $ciphersuite = shift; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return $ciphersuite; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-16 20:06:41 +08:00
										 |  |  | #Update all the underlying records with the modified data from this message | 
					
						
							| 
									
										
										
										
											2021-03-18 23:25:42 +08:00
										 |  |  | #Note: Only supports TLSv1.3 and ETM encryption | 
					
						
							| 
									
										
										
										
											2015-06-16 20:06:41 +08:00
										 |  |  | sub repack | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     my $self = shift; | 
					
						
							|  |  |  |     my $msgdata; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     my $numrecs = $#{$self->records}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     $self->set_message_contents(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-01-11 21:18:07 +08:00
										 |  |  |     my $lenlo = length($self->data) & 0xff; | 
					
						
							|  |  |  |     my $lenhi = length($self->data) >> 8; | 
					
						
							| 
									
										
										
										
											2015-06-16 20:06:41 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-01-11 21:18:07 +08:00
										 |  |  |     if ($self->{isdtls}) { | 
					
						
							|  |  |  |         my $msgfraghi = $self->msgfrag >> 8; | 
					
						
							|  |  |  |         my $msgfraglo = $self->msgfrag & 0xff; | 
					
						
							|  |  |  |         my $msgfragoffshi = $self->msgfragoffs >> 8; | 
					
						
							|  |  |  |         my $msgfragoffslo = $self->msgfragoffs & 0xff; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $msgdata = pack('CnCnnCnC', $self->mt, $lenhi, $lenlo, $self->msgseq, | 
					
						
							|  |  |  |                                     $msgfraghi, $msgfraglo, | 
					
						
							|  |  |  |                                     $msgfragoffshi, $msgfragoffslo).$self->data; | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |         $msgdata = pack('CnC', $self->mt, $lenhi, $lenlo).$self->data; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2015-06-16 20:06:41 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if ($numrecs == 0) { | 
					
						
							|  |  |  |         #The message is fully contained within one record | 
					
						
							|  |  |  |         my ($rec) = @{$self->records}; | 
					
						
							|  |  |  |         my $recdata = $rec->decrypt_data; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-16 23:47:55 +08:00
										 |  |  |         my $old_length; | 
					
						
							| 
									
										
										
										
											2024-01-11 21:18:07 +08:00
										 |  |  |         my $msg_header_len = $self->{isdtls} ? DTLS_MESSAGE_HEADER_LENGTH | 
					
						
							|  |  |  |                                              : TLS_MESSAGE_HEADER_LENGTH; | 
					
						
							| 
									
										
										
										
											2015-09-16 23:47:55 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |         # We use empty message_frag_lens to indicates that pre-repacking, | 
					
						
							|  |  |  |         # the message wasn't present. The first fragment length doesn't include | 
					
						
							|  |  |  |         # the TLS header, so we need to check and compute the right length. | 
					
						
							|  |  |  |         if (@{$self->message_frag_lens}) { | 
					
						
							| 
									
										
										
										
											2024-01-11 21:18:07 +08:00
										 |  |  |             $old_length = ${$self->message_frag_lens}[0] + $msg_header_len; | 
					
						
							| 
									
										
										
										
											2015-09-16 23:47:55 +08:00
										 |  |  |         } else { | 
					
						
							|  |  |  |             $old_length = 0; | 
					
						
							| 
									
										
										
										
											2015-06-16 20:06:41 +08:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-16 23:47:55 +08:00
										 |  |  |         my $prefix = substr($recdata, 0, $self->startoffset); | 
					
						
							|  |  |  |         my $suffix = substr($recdata, $self->startoffset + $old_length); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $rec->decrypt_data($prefix.($msgdata).($suffix)); | 
					
						
							|  |  |  |         # TODO(openssl-team): don't keep explicit lengths. | 
					
						
							|  |  |  |         # (If a length override is ever needed to construct invalid packets, | 
					
						
							|  |  |  |         #  use an explicit override field instead.) | 
					
						
							|  |  |  |         $rec->decrypt_len(length($rec->decrypt_data)); | 
					
						
							| 
									
										
										
										
											2021-03-18 23:25:42 +08:00
										 |  |  |         # Only support re-encryption for TLSv1.3 and ETM. | 
					
						
							|  |  |  |         if ($rec->encrypted()) { | 
					
						
							|  |  |  |             if (TLSProxy::Proxy->is_tls13()) { | 
					
						
							|  |  |  |                 #Add content type (1 byte) and 16 tag bytes | 
					
						
							|  |  |  |                 $rec->data($rec->decrypt_data | 
					
						
							|  |  |  |                     .pack("C", TLSProxy::Record::RT_HANDSHAKE).("\0"x16)); | 
					
						
							|  |  |  |             } elsif ($rec->etm()) { | 
					
						
							|  |  |  |                 my $data = $rec->decrypt_data; | 
					
						
							|  |  |  |                 #Add padding | 
					
						
							|  |  |  |                 my $padval = length($data) % 16; | 
					
						
							|  |  |  |                 $padval = 15 - $padval; | 
					
						
							|  |  |  |                 for (0..$padval) { | 
					
						
							|  |  |  |                     $data .= pack("C", $padval); | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 #Add MAC. Assumed to be 20 bytes | 
					
						
							|  |  |  |                 foreach my $macval (0..19) { | 
					
						
							|  |  |  |                     $data .= pack("C", $macval); | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 if ($rec->version() >= TLSProxy::Record::VERS_TLS_1_1) { | 
					
						
							|  |  |  |                     #Explicit IV | 
					
						
							|  |  |  |                     $data = ("\0"x16).$data; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |                 $rec->data($data); | 
					
						
							|  |  |  |             } else { | 
					
						
							|  |  |  |                 die "Unsupported encryption: No ETM"; | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2017-01-05 20:34:46 +08:00
										 |  |  |         } else { | 
					
						
							|  |  |  |             $rec->data($rec->decrypt_data); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2021-03-18 23:25:42 +08:00
										 |  |  |         $rec->len(length($rec->data)); | 
					
						
							| 
									
										
										
										
											2015-06-16 20:06:41 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |         #Update the fragment len in case we changed it above | 
					
						
							| 
									
										
										
										
											2024-01-11 21:18:07 +08:00
										 |  |  |         ${$self->message_frag_lens}[0] = length($msgdata) - $msg_header_len; | 
					
						
							| 
									
										
										
										
											2015-06-16 20:06:41 +08:00
										 |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     #Note we don't currently support changing a fragmented message length | 
					
						
							|  |  |  |     my $recctr = 0; | 
					
						
							|  |  |  |     my $datadone = 0; | 
					
						
							|  |  |  |     foreach my $rec (@{$self->records}) { | 
					
						
							|  |  |  |         my $recdata = $rec->decrypt_data; | 
					
						
							|  |  |  |         if ($recctr == 0) { | 
					
						
							|  |  |  |             #This is the first record | 
					
						
							|  |  |  |             my $remainlen = length($recdata) - $self->startoffset; | 
					
						
							|  |  |  |             $rec->data(substr($recdata, 0, $self->startoffset) | 
					
						
							|  |  |  |                        .substr(($msgdata), 0, $remainlen)); | 
					
						
							|  |  |  |             $datadone += $remainlen; | 
					
						
							|  |  |  |         } elsif ($recctr + 1 == $numrecs) { | 
					
						
							|  |  |  |             #This is the last record | 
					
						
							|  |  |  |             $rec->data(substr($msgdata, $datadone)); | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |             #This is a middle record | 
					
						
							|  |  |  |             $rec->data(substr($msgdata, $datadone, length($rec->data))); | 
					
						
							|  |  |  |             $datadone += length($rec->data); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         $recctr++; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #To be overridden by sub-classes | 
					
						
							|  |  |  | sub set_message_contents | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #Read only accessors | 
					
						
							|  |  |  | sub server | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     my $self = shift; | 
					
						
							|  |  |  |     return $self->{server}; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #Read/write accessors | 
					
						
							|  |  |  | sub mt | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     my $self = shift; | 
					
						
							|  |  |  |     if (@_) { | 
					
						
							|  |  |  |       $self->{mt} = shift; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return $self->{mt}; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2024-01-11 21:18:07 +08:00
										 |  |  | sub msgseq | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     my $self = shift; | 
					
						
							|  |  |  |     if (@_) { | 
					
						
							|  |  |  |         $self->{msgseq} = shift; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return $self->{msgseq}; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | sub msgfrag | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     my $self = shift; | 
					
						
							|  |  |  |     if (@_) { | 
					
						
							|  |  |  |         $self->{msgfrag} = shift; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return $self->{msgfrag}; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | sub msgfragoffs | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     my $self = shift; | 
					
						
							|  |  |  |     if (@_) { | 
					
						
							|  |  |  |         $self->{msgfragoffs} = shift; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return $self->{msgfragoffs}; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2015-06-16 20:06:41 +08:00
										 |  |  | sub data | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     my $self = shift; | 
					
						
							|  |  |  |     if (@_) { | 
					
						
							|  |  |  |       $self->{data} = shift; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return $self->{data}; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | sub records | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     my $self = shift; | 
					
						
							|  |  |  |     if (@_) { | 
					
						
							|  |  |  |       $self->{records} = shift; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return $self->{records}; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | sub startoffset | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     my $self = shift; | 
					
						
							|  |  |  |     if (@_) { | 
					
						
							|  |  |  |       $self->{startoffset} = shift; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return $self->{startoffset}; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | sub message_frag_lens | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     my $self = shift; | 
					
						
							|  |  |  |     if (@_) { | 
					
						
							|  |  |  |       $self->{message_frag_lens} = shift; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return $self->{message_frag_lens}; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2015-09-16 23:47:55 +08:00
										 |  |  | sub encoded_length | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     my $self = shift; | 
					
						
							| 
									
										
										
										
											2024-01-11 21:18:07 +08:00
										 |  |  |     my $msg_header_len = $self->{isdtls} ? DTLS_MESSAGE_HEADER_LENGTH | 
					
						
							|  |  |  |                                          : TLS_MESSAGE_HEADER_LENGTH; | 
					
						
							|  |  |  |     return $msg_header_len + length($self->data); | 
					
						
							| 
									
										
										
										
											2015-09-16 23:47:55 +08:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2019-01-05 00:55:15 +08:00
										 |  |  | sub dupext | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     my $self = shift; | 
					
						
							|  |  |  |     if (@_) { | 
					
						
							|  |  |  |         $self->{dupext} = shift; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return $self->{dupext}; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2017-01-20 20:08:51 +08:00
										 |  |  | sub successondata | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     my $class = shift; | 
					
						
							|  |  |  |     if (@_) { | 
					
						
							|  |  |  |         $successondata = shift; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return $successondata; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2015-06-16 20:06:41 +08:00
										 |  |  | 1; |