File Coverage

blib/lib/Protocol/TLS/RecordLayer.pm
Criterion Covered Total %
statement 54 61 88.5
branch 10 18 55.5
condition n/a
subroutine 12 12 100.0
pod 0 2 0.0
total 76 93 81.7


line stmt bran cond sub pod time code
1             package Protocol::TLS::RecordLayer;
2 2     2   11 use strict;
  2         4  
  2         64  
3 2     2   12 use warnings;
  2         4  
  2         59  
4 2     2   11 use Protocol::TLS::Trace qw(tracer);
  2         4  
  2         114  
5 2     2   1260 use Protocol::TLS::Constants qw(is_tls_version :versions :c_types);
  2         5  
  2         544  
6 2     2   1328 use Protocol::TLS::ChangeCipherSpec;
  2         4  
  2         59  
7 2     2   1168 use Protocol::TLS::Handshake;
  2         5  
  2         64  
8 2     2   1127 use Protocol::TLS::Alert;
  2         4  
  2         63  
9 2     2   1011 use Protocol::TLS::Application;
  2         5  
  2         57  
10 2     2   1026 use Protocol::TLS::Compression;
  2         6  
  2         52  
11 2     2   1107 use Protocol::TLS::Protection;
  2         6  
  2         1144  
12              
13             my %content_types = (
14             &CTYPE_CHANGE_CIPHER_SPEC => 'ChangeCipherSpec',
15             &CTYPE_ALERT => 'Alert',
16             &CTYPE_HANDSHAKE => 'Handshake',
17             &CTYPE_APPLICATION_DATA => 'Application',
18             );
19              
20             my %decoder =
21             map { $_ => \&{ 'Protocol::TLS::' . $content_types{$_} . '::decode' } }
22             keys %content_types;
23              
24             my %encoder =
25             map { $_ => \&{ 'Protocol::TLS::' . $content_types{$_} . '::encode' } }
26             keys %content_types;
27              
28             sub record_decode {
29 35     35 0 82 my ( $ctx, $buf_ref, $buf_offset ) = @_;
30 35 100       180 return 0 if length($$buf_ref) - $buf_offset < 5;
31 20         188 my ( $type, $version, $length ) = unpack "x${buf_offset}Cn2", $$buf_ref;
32              
33 20 50       101 if ( !is_tls_version($version) ) {
34 0         0 tracer->debug(
35             sprintf "Unsupported TLS version: %i.%i\n",
36             int( $version / 256 ),
37             $version % 256
38             );
39              
40             # Unsupported TLS version
41 0         0 $ctx->error();
42 0         0 return undef;
43             }
44              
45             # Unknown content type
46 20 50       76 if ( !exists $content_types{$type} ) {
47 0         0 tracer->debug("Unknown content type: $type\n");
48              
49             # Unknown content type
50 0         0 $ctx->error();
51 0         0 return undef;
52             }
53              
54 20 50       76 return 0
55             if length($$buf_ref) - $buf_offset - 5 - $length < 0;
56              
57 20         114 my $decrypted = Protocol::TLS::Protection::decode( $ctx, $type, $version,
58             $buf_ref, $buf_offset + 5, $length );
59              
60 20 50       65 return undef unless defined $decrypted;
61              
62 20         106 my $decompressed = Protocol::TLS::Compression::decode( $ctx, \$decrypted, 0,
63             length $decrypted );
64              
65 20 50       89 return undef unless defined $decompressed;
66              
67 20         58 $ctx->{fragment} .= $decompressed;
68 20         40 my $f_len = length $ctx->{fragment};
69 20         39 my $offset = 0;
70              
71 20         54 while ( $offset < $f_len ) {
72             my $readed_len = $decoder{$type}
73 20         140 ->( $ctx, \$ctx->{fragment}, $offset, $f_len - $offset );
74 20 50       67 return undef unless defined $readed_len;
75 20 50       63 last unless $readed_len;
76 20         66 $offset += $readed_len;
77             }
78              
79 20 50       57 if ( $f_len == $offset ) {
80 20         55 $ctx->{fragment} = '';
81             }
82             else {
83 0         0 substr $ctx->{fragment}, 0, $offset, '';
84             }
85              
86 20         109 return 5 + $length;
87             }
88              
89             sub record_encode {
90 20     20 0 88 my ( $ctx, $version, $type ) = splice @_, 0, 3;
91             my $payload = Protocol::TLS::Protection::encode(
92             $ctx, $version, $type,
93             Protocol::TLS::Compression::encode(
94 20         179 $ctx, $encoder{$type}->( $ctx, @_ )
95             )
96             );
97 20         122 pack( 'Cn2', $type, $version, length $payload ) . $payload;
98             }
99              
100             1