1use warnings; 2use strict; 3use Test::More tests => 73; 4use Test::Exception; 5 6use Crypt::MatrixSSL3 qw(:all); 7 8my $certFile = 't/cert/testserver.crt'; 9my $privFile = 't/cert/testserver.key'; 10my $privPass = undef; 11my $trustedCAcertFiles = 't/cert/testca.crt'; 12 13my ($Server_Keys, $Client_Keys); 14my ($Server_SSL, $Client_SSL); 15 16 17######## 18# Init # 19######## 20 21lives_ok { $Server_Keys = Crypt::MatrixSSL3::Keys->new() } 22 'Keys->new (server)'; 23is PS_SUCCESS, $Server_Keys->load_rsa($certFile, $privFile, $privPass, undef), 24 '$Server_Keys->load_rsa'; 25lives_ok { $Server_SSL = Crypt::MatrixSSL3::Server->new($Server_Keys, undef) } 26 'Server->new'; 27 28lives_ok { $Client_Keys = Crypt::MatrixSSL3::Keys->new() } 29 'Keys->new (client)'; 30is PS_SUCCESS, $Client_Keys->load_rsa(undef, undef, undef, $trustedCAcertFiles), 31 '$Client_Keys->load_rsa'; 32lives_ok { $Client_SSL = Crypt::MatrixSSL3::Client->new($Client_Keys, undef, 0, undef, undef, undef) } 33 'Client->new'; 34 35############# 36# Handshake # 37############# 38 39my ($client2server, $server2client) = (q{}, q{}); 40my ($client_rc, $server_rc); 41while (1) { 42 $server_rc = _decode($Server_SSL, $client2server, $server2client); 43 $client_rc = _decode($Client_SSL, $server2client, $client2server); 44 last if $client_rc || $server_rc; 45} 46is 1, $server_rc, 'handshake complete (server)'; 47is 1, $client_rc, 'handshake complete (client)'; 48ok !length $client2server, 'client outbuf empty after handshake'; 49ok !length $server2client, 'server outbuf empty after handshake'; 50 51####### 52# I/O # 53####### 54 55# Simple string, twice 56 57my $s = "Hello MatrixSSL!\0\n"; 58my $tmp = $s; 59my $buf; 60 61ok $Client_SSL->encode_to_outdata($s) > 0, 62 '$Client_SSL->encode_to_outdata'; 63is $tmp, $s, 64 q{encode_to_outdata doesn't destroy input string}; 65is undef, _decode($Client_SSL, $server2client, $client2server); 66ok length $client2server, 67 'got some outbuf (client)'; 68$tmp = $client2server; 69ok $Client_SSL->encode_to_outdata($s) > 0, 70 '$Client_SSL->encode_to_outdata'; 71is undef, _decode($Client_SSL, $server2client, $client2server); 72ok length $tmp < length $client2server, 73 'outbuf grow (client)'; 74 75is undef, _decode($Server_SSL, $client2server, $server2client, $buf); 76is $buf, $s.$s, 77 'decoded ok (server)'; 78ok !length $client2server, 79 'outbuf empty (client)'; 80ok !length $server2client, 81 'outbuf empty (server)'; 82 83# SSL_MAX_PLAINTEXT_LEN 84 85$s = 'abc' x 123456; 86$tmp = $s; 87$buf = q{}; 88while (length $tmp) { 89 ok $Client_SSL->encode_to_outdata(substr($tmp, 0, SSL_MAX_PLAINTEXT_LEN, q{})) > 0, 90 'encode_to_outdata up to SSL_MAX_PLAINTEXT_LEN (client)'; 91} 92 is undef, _decode($Client_SSL, $server2client, $client2server), 93 'encoding'; 94while (length $client2server) { 95 is undef, _decode($Server_SSL, $client2server, $server2client, $buf), 96 'decoding'; 97} 98ok $buf eq $s, 99 'string split into SSL_MAX_PLAINTEXT_LEN chains decoded ok'; 100ok !length $client2server, 101 'outbuf empty (client)'; 102ok !length $server2client, 103 'outbuf empty (server)'; 104 105# More than SSL_MAX_PLAINTEXT_LEN 106 107$s = 'x' x (SSL_MAX_PLAINTEXT_LEN+1); 108is PS_LIMIT_FAIL, $Client_SSL->encode_to_outdata($s), 109 'encode_to_outdata SSL_MAX_PLAINTEXT_LEN+1 failed'; 110 111####### 112# Fin # 113####### 114 115undef $Server_SSL; 116undef $Client_SSL; 117undef $Server_Keys; 118undef $Client_Keys; 119ok 1, 'matrixSslClose'; 120 121 122########### 123# Helpers # 124########### 125 126sub _decode { 127 my ($ssl) = @_; # other 3 params must be modified in place 128 while (my $n = $ssl->get_readbuf($_[1])) { 129 die error($n) if $n < 0; 130 my $rc = $ssl->received_data($n, my $buf); 131RC: 132 if ($rc == MATRIXSSL_REQUEST_SEND) { last } 133 elsif ($rc == MATRIXSSL_REQUEST_RECV) { next } 134 elsif ($rc == MATRIXSSL_HANDSHAKE_COMPLETE) { return 1 } 135 elsif ($rc == MATRIXSSL_RECEIVED_ALERT) { alert($buf); return -1 } 136 elsif ($rc == MATRIXSSL_APP_DATA) { $_[3].=$buf } 137 elsif ($rc == MATRIXSSL_SUCCESS) { last } 138 else { die error($rc)} 139 $rc = $ssl->processed_data($buf); 140 goto RC; 141 } 142 while (my $n = $ssl->get_outdata($_[2])) { 143 die error($n) if $n < 0; 144 my $rc = $ssl->sent_data($n); 145 if ($rc == MATRIXSSL_REQUEST_SEND) { next } 146 elsif ($rc == MATRIXSSL_SUCCESS) { last } 147 elsif ($rc == MATRIXSSL_REQUEST_CLOSE) { return -1 } 148 elsif ($rc == MATRIXSSL_HANDSHAKE_COMPLETE) { return 1 } 149 else { die error($rc)} 150 } 151 return; 152} 153 154sub error { 155 my $rc = get_ssl_error($_[0]); 156 return sprintf "MatrixSSL error %d: %s\n", $rc, $rc; 157} 158sub alert { 159 my ($level, $descr) = get_ssl_alert($_[0]); 160 diag sprintf "MatrixSSL alert: level %d: %s, desc %d: %s\n", $level, $level, $descr, $descr; 161 return; 162} 163 164