File Coverage

blib/lib/Protocol/TLS/RecordLayer.pm
Criterion Covered Total %
statement 45 51 88.2
branch 8 14 57.1
condition n/a
subroutine 12 12 100.0
pod 0 2 0.0
total 65 79 82.2


line stmt bran cond sub pod time code
1             package Protocol::TLS::RecordLayer;
2 2     2   10 use strict;
  2         4  
  2         69  
3 2     2   10 use warnings;
  2         2  
  2         57  
4 2     2   14 use Protocol::TLS::Trace qw(tracer);
  2         3  
  2         218  
5 2     2   845 use Protocol::TLS::Constants qw(is_tls_version :versions :c_types);
  2         5  
  2         551  
6 2     2   1003 use Protocol::TLS::ChangeCipherSpec;
  2         5  
  2         62  
7 2     2   1044 use Protocol::TLS::Handshake;
  2         6  
  2         69  
8 2     2   945 use Protocol::TLS::Alert;
  2         4  
  2         64  
9 2     2   807 use Protocol::TLS::Application;
  2         5  
  2         74  
10 2     2   853 use Protocol::TLS::Compression;
  2         4  
  2         61  
11 2     2   838 use Protocol::TLS::Protection;
  2         5  
  2         990  
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 47 my ( $ctx, $buf_ref, $buf_offset ) = @_;
30 35 100       166 return 0 if length($$buf_ref) - $buf_offset < 5;
31 20         108 my ( $type, $version, $length ) = unpack "x${buf_offset}Cn2", $$buf_ref;
32              
33 20 50       69 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       62 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       59 return 0
55             if length($$buf_ref) - $buf_offset - 5 - $length < 0;
56              
57 20         167 my $decrypted = Protocol::TLS::Protection::decode( $ctx, $type, $version,
58             $buf_ref, $buf_offset + 5, $length );
59              
60 20 50       56 return undef unless defined $decrypted;
61              
62 20         74 my $decompressed = Protocol::TLS::Compression::decode( $ctx, \$decrypted, 0,
63             length $decrypted );
64              
65 20 50       53 return undef unless defined $decompressed;
66              
67             return undef
68 20 50       101 unless defined $decoder{$type}
69             ->( $ctx, \$decompressed, 0, length $decompressed );
70              
71 20         83 return 5 + $length;
72             }
73              
74             sub record_encode {
75 20     20 0 46 my ( $ctx, $version, $type ) = splice @_, 0, 3;
76 20         126 my $payload = Protocol::TLS::Protection::encode(
77             $ctx, $version, $type,
78             Protocol::TLS::Compression::encode(
79             $ctx, $encoder{$type}->( $ctx, @_ )
80             )
81             );
82 20         102 pack( 'Cn2', $type, $version, length $payload ) . $payload;
83             }
84              
85             1