powerman / perl-Crypt-MatrixSSL3

Perl module: Crypt::MatrixSSL3 - Perl extension for SSL and TLS using MatrixSSL.org
https://metacpan.org/release/Crypt-MatrixSSL3
Other
1 stars 1 forks source link

Build Status Coverage Status

NAME

Crypt::MatrixSSL3 - Perl extension for SSL and TLS using MatrixSSL.org v3.9.3

VERSION

This document describes Crypt::MatrixSSL3 version v3.9.3

SYNOPSIS

use Crypt::MatrixSSL3;

# 1. See the MatrixSSL documentation.
# 2. See example scripts included in this package:
#       ssl_client.pl
#       ssl_server.pl
#       functions.pl

DESCRIPTION

Crypt::MatrixSSL3 lets you use the MatrixSSL crypto library (see http://matrixssl.org/) from Perl. With this module, you will be able to easily write SSL and TLS client and server programs.

MatrixSSL includes everything you need, all in under 50KB.

You will need a "C" compiler to build this, unless you're getting the ".ppm" prebuilt Win32 version. Crypt::MatrixSSL3 builds cleanly on (at least) Windows, Linux, and Macintosh machines.

MatrixSSL is an Open Source (GNU General Public License) product, and is also available commercially if you need freedom from GNU rules.

Everything you need is included here, but check the MatrixSSL.org web site to make sure you've got the latest version of the MatrixSSL "C" code if you like (it's in the directory "./inc" of this package if you want to replace the included version from the MatrixSSL.org download site).

API BACKWARD COMPATIBILITY AND STATUS

MatrixSSL tends to make incompatible API changes in minor releases, so every next version of Crypt::MatrixSSL3 may have incompatible API changes!

This version adds several new features which isn't well-tested yet and thus considered unstable:

TERMINOLOGY

When a client establishes an SSL connection without sending a SNI extension in its CLIENT_HELLO message we say that the client connects to the default server.

If a SNI extension is present then the client connects to a virtual host.

EXPORTS

Constants and functions can be exported using different tags. Use tag ':all' to export everything.

By default (tag ':DEFAULT') only SSL_MAX_PLAINTEXT_LEN and return code constants (tag ':RC') will be exported.

VARIABLES

CA_CERTIFICATES

$keys->load_rsa( undef, undef, undef, $Crypt::MatrixSSL3::CA_CERTIFICATES )

Scalar. Contains path to ca-certificates.crt file distributed with this module. This file is generated by `mk-matrixssl-ca-certificates.pl` and contains all certificates from current Firefox CA bundle supported by MatrixSSL.

FUNCTIONS

Some MatrixSSL functions are not accessible from Perl.

These functions implement optimization which is useless in Perl:

matrixSslGetWritebuf
matrixSslEncodeWritebuf

Open

Close

Crypt::MatrixSSL3::Open();
Crypt::MatrixSSL3::Close();

If you write server intensive applications it is still better to control how often the MatrixSSL library gets initialized/deinitialized. For this you can call Open() to initialize the library at the start of you application and (optionally) Close() to deinitialize the library when your application ends.

If you won't call Open() manually then these functions will be called automatically before creating first object of any class (::Keys, ::SessID, ::Client, ::Server or ::HelloExt) and after last object will be destroyed:

matrixSslOpen
matrixSslClose

capabilities

$caps = Crypt::MatrixSSL3::capabilities();

Returns a bitwise OR combination of the following constants:

SHARED_SESSION_CACHE_ENABLED     - shared session cache between multiple processes is enabled
STATELESS_TICKETS_ENABLED        - stateless ticket session resuming support is enabled
DH_PARAMS_ENABLED                - loading the DH param for DH cipher suites is enabled
ALPN_ENABLED                     - Application Layer Protocol Negotiation callback support is enabled
SNI_ENABLED                      - Server Name Identification (virtual hosts) support is enabled
OCSP_STAPLES_ENABLED             - handling of the "status_request" TLS extension by responding with an OCSP staple is enabled
CERTIFICATE_TRANSPARENCY_ENABLED - handling of the "signed_certificate_timestamp" TLS extension is enabled

Before using any of these features it's a good idea to test if MatrixSSL is supporting them.

set_cipher_suite_enabled_status

$rc = set_cipher_suite_enabled_status( $cipherId, $status );

matrixSslSetCipherSuiteEnabledStatus( NULL, $cipherId, $status )

If this function will be used, matrixSslClose() will be never called.

get_ssl_alert

($level, $descr) = get_ssl_alert( $ptBuf );
$descr           = get_ssl_alert( $ptBuf );

Unpack alert level and description from $ptBuf returned by $ssl->received_data() or $ssl->processed_data().

Return ($level, $descr) in list context, and $descr in scalar context. Both $level and $descr are dualvars (code in numeric context and text in string context).

get_ssl_error

$rc = get_ssl_error( $rc );

Return dualvar for this error code (same as $rc in numeric context and text error name in string context).

refresh_OCSP_staple

$rc = refresh_OCSP_staple( $server_index, $index, $DERfile );

Used to refresh an already loaded OCSP staple for a virtual host.

Parameters:

Returns PS_SUCCESS if the update was successful.

refresh_SCT_buffer

$sct_array_size = refresh_SCT_buffer( $server_index, $index, $SCT_params );

Used to refresh an already loaded CT extension data buffer for a virtual host.

Parameters:

Returns the number of files loaded (if this is 0 there was an error loading one of the files).

refresh_ALPN_data

$num_protocols = refresh_ALPN_data( $server_index, $index, $protocols );

Used to refresh the application protocols for a default server or for a virtual host.

Parameters:

Returns the number of files loaded in order to build extension data.

set_VHIndex_callback

set_VHIndex_callback( \&VHIndexCallback );

More information about "VHIndexCallback" in the "CALLBACKS" section.

set_ALPN_callback

set_ALPN_callback( \&ALPNCallback );

More information about "ALPNCallback" in the "CALLBACKS" section.

create_SSL_server

$server_index = create_SSL_server();

Tells the XS module to allocate a new server structure. The returned index must be saved and then used one time to initialize the server structure and then each time a new client connection is accepted in order to set SNI/ALPN callbacks.

CLASSES

Constructors for all classes will throw exception on error instead of returning error as matrixSslNew*() functions do. Exception will be thrown using croak($return_code), so to get $return_code from $@ you should convert it back to number:

eval { $client = Crypt::MatrixSSL3::Client->new(...) };
$rc = 0+$@ if $@;

Crypt::MatrixSSL3::Keys

new

$keys = Crypt::MatrixSSL3::Keys->new();

matrixSslNewKeys( $keys )

Return new object $keys. Throw exception if matrixSslNewKeys() doesn't return PS_SUCCESS. When this object will be destroyed will call:

matrixSslDeleteKeys( $keys )

load_rsa

$rc = $keys->load_rsa( $certFile,
    $privFile, $privPass, $trustedCAcertFiles );

matrixSslLoadRsaKeys( $keys, $certFile,
    $privFile, $privPass, $trustedCAcertFiles )

load_rsa_mem

$rc = $keys->load_rsa_mem( $cert, $priv, $trustedCA );

matrixSslLoadRsaKeysMem( $keys, $cert, length $cert,
    $priv, length $priv, $trustedCA, length $trustedCA )

load_ecc

$rc = $keys->load_ecc( $certFile,
    $privFile, $privPass, $trustedCAcertFiles );

matrixSslLoadEcKeys( $keys, $certFile,
    $privFile, $privPass, $trustedCAcertFiles )

load_rsa_mem

$rc = $keys->load_ecc_mem( $cert, $priv, $trustedCA );

matrixSslLoadEcKeysMem( $keys, $cert, length $cert,
    $priv, length $priv, $trustedCA, length $trustedCA )

load_pkcs12

$rc = $keys->load_pkcs12( $p12File, $importPass, $macPass, $flags );

matrixSslLoadPkcs12( $keys, $p12File, $importPass, length $importPass,
    $macPass, length $macPass, $flags )

load_DH_params

$rc = $keys->load_DH_params( $DH_params_file );

matrixSslLoadDhParams ( $keys, $DH_params_file )

load_session_ticket_keys

$rc = $keys->load_session_ticket_keys( $name, $symkey, $hashkey );

matrixSslLoadSessionTicketKeys ( $keys, $name, $symkey, length $symkey,
    $haskkey, length $hashkey )

load_OCSP_response

$rc = $keys->load_OCSP_response( $OCSP_file );

matrixSslLoadOCSPResponse ( $keys, $OCSPResponse, $OCSPResponseLen )

load_SCT_response

$rc = $keys->load_SCT_response( $SCT_params );

matrixSslLoadSCTResponse ( $keys, $SCTResponse, $SCTResponseLen )

Server side.

Crypt::MatrixSSL3::SessID

new

$sessID = Crypt::MatrixSSL3::SessID->new();

Return new object $sessID representing (sslSessionId_t*) type. Throw exception if failed to allocate memory. When this object will be destroyed will free memory, so you should keep this object while there are still Client/Server session which use this $sessID.

clear

$sessID->clear();

matrixSslClearSessionId($sessID)

Crypt::MatrixSSL3::Client

new

$ssl = Crypt::MatrixSSL3::Client->new(
    $keys, $sessID, \@cipherSuites,
    \&certValidator, $expectedName,
    $extensions, \&extensionCback,
);

matrixSslNewClientSession( $ssl,
    $keys, $sessID, \@cipherSuites,
    \&certValidator, $expectedName,
    $extensions, \&extensionCback,
)

Return new object $ssl. Throw exception if matrixSslNewClientSession() doesn't return MATRIXSSL_REQUEST_SEND. When this object will be destroyed will call:

matrixSslDeleteSession( $ssl )

More information about callbacks "certValidator" and "extensionCback" in the "CALLBACKS" section.

Crypt::MatrixSSL3::Server

new

$ssl = Crypt::MatrixSSL3::Server->new( $keys, \&certValidator );

matrixSslNewServerSession( $ssl, $keys, \&certValidator )

Return new object $ssl. Throw exception if matrixSslNewServerSession() doesn't return PS_SUCCESS. When this object will be destroyed will call:

matrixSslDeleteSession( $ssl )

More information about callback "certValidator" in the "CALLBACKS" section.

init_SNI

$ssl->init_SNI( $sserver_index, $sni_params );

This function should be called only once when the server is initialized.

Parameters:

set_server_params

$ssl->set_server_params( $server_index, $sv_params );

Used to set the server supported protocols used when a client send a TLS ALPN extension.

Note that this function call only affects the default server. Virtual hosts are managed by using the $ssl->init_SNI(...).

See $ssl->init_SNI(...) for usage.

Parameters:

set_callbacks

$ssl->set_callbacks( $server_index, $ssl_id );

Parameters:

Crypt::MatrixSSL3::Client and Crypt::MatrixSSL3::Server

get_outdata

$rc = $ssl->get_outdata( $outBuf );

Unlike C API, it doesn't set $outBuf to memory location inside MatrixSSL, but instead it append buffer returned by C API to the end of $outBuf.

matrixSslGetOutdata( $ssl, $tmpBuf )
$outBuf .= $tmpBuf

Throw exception if matrixSslGetOutdata() returns < 0.

sent_data

$rc = $ssl->sent_data( $bytes );

matrixSslSentData( $ssl, $bytes )

received_data

$rc = $ssl->received_data( $inBuf, $ptBuf );

$n = matrixSslGetReadbuf( $ssl, $buf )
$n = min($n, length $inBuf)
$buf = substr($inBuf, 0, $n, q{})
matrixSslReceivedData( $ssl, $n, $ptBuf, $ptLen )

Combines two calls: matrixSslGetReadbuf() and matrixSslReceivedData(). It copy data from beginning of $inBuf into buffer returned by matrixSslGetReadbuf() and cut copied data from beginning of $inBuf (it may copy less bytes than $inBuf contain if size of buffer provided by MatrixSSL will be smaller). Then it calls matrixSslReceivedData() to get $rc and may fill $ptBuf with received alert or application data.

It is safe to call it with empty $inBuf, but this isn't a good idea performance-wise.

Throw exception if matrixSslGetReadbuf() returns <= 0.

processed_data

$rc = $ssl->processed_data( $ptBuf );

matrixSslProcessedData( $ssl, $ptBuf, $ptLen )

In case matrixSslReceivedData() or matrixSslProcessedData() will return MATRIXSSL_RECEIVED_ALERT, you can get alert level and description from $ptBuf:

my ($level, $descr) = get_ssl_alert($ptBuf);

encode_to_outdata

$rc = $ssl->encode_to_outdata( $outBuf );

matrixSslEncodeToOutdata( $ssl, $outBuf, length $outBuf )

encode_closure_alert

$rc = $ssl->encode_closure_alert();

matrixSslEncodeClosureAlert( $ssl )

encode_rehandshake

$rc = $ssl->encode_rehandshake(
    $keys, \&certValidator, $sessionOption, \@cipherSuites,
);

matrixSslEncodeRehandshake( $ssl, $keys, \&certValidator,
    $sessionOption, \@cipherSuites )

More information about callback "certValidator" in the "CALLBACKS" section.

set_cipher_suite_enabled_status

$rc = $ssl->set_cipher_suite_enabled_status( $cipherId, $status );

matrixSslSetCipherSuiteEnabledStatus( $ssl, $cipherId, $status )

get_anon_status

$anon = $ssl->get_anon_status();

matrixSslGetAnonStatus( $ssl, $anon )

Crypt::MatrixSSL3::HelloExt

new

$extension = Crypt::MatrixSSL3::HelloExt->new();

matrixSslNewHelloExtension>( $extension )

Return new object $extension. Throw exception if matrixSslNewHelloExtension() doesn't return PS_SUCCESS. When this object will be destroyed will call:

matrixSslDeleteHelloExtension( $extension )

load

$rc = $extension->load( $ext, $extType );

matrixSslLoadHelloExtension( $extension, $ext, length $ext, $extType )

CALLBACKS

certValidator

Will be called with two scalar params: $certInfo and $alert (unlike C callback which also have $ssl param).

Param $certInfo instead of (psX509Cert_t *) will contain reference to array with certificates. Each certificate will be hash in this format:

notBefore       => $notBefore,
notAfter        => $notAfter,
subjectAltName  => {
    dns             => $dns,
    uri             => $uri,
    email           => $email,
},
subject        => {
    country         => $country,
    state           => $state,
    locality        => $locality,
    organization    => $organization,
    orgUnit         => $orgUnit,
    commonName      => $commonName,
},
issuer         => {
    country         => $country,
    state           => $state,
    locality        => $locality,
    organization    => $organization,
    orgUnit         => $orgUnit,
    commonName      => $commonName,
},
authStatus     => $authStatus,

This callback must return single scalar with integer value (as described in MatrixSSL documentation). If callback die(), then warning will be printed, and execution will continue assuming callback returned -1.

extensionCback

Will be called with two scalar params: $type and $data (unlike C callback which also have $ssl and length($data) params).

This callback must return single scalar with integer value (as described in MatrixSSL documentation). If callback die(), then warning will be printed, and execution will continue assuming callback returned -1.

ALPNCallback

Will be called when a client sends an ALPN extension and a successful application protocol has been negotiated. If the server doesn't implement any of the client's protocols the XS module will send an appropriate response and the client will receive a SSL_ALERT_NO_APP_PROTOCOL alert.

Will be called with 2 parameters:

$ssl_id - this is the $ssl_id used in the $ssl->set_callbacks(...) call
$app_proto - scalar with the negociated protocol name

VHIndexCallback

Will be called whenever we have a successful match against the hostname specified by the client in its SNI extension. This will inform the Perl code which virtual host the current SSL session belongs to.

Will be called with 3 parameters:

$ssl_id - this is the $ssl_id used in the $ssl->set_callbacks(...) call
$index - a 0-based int specifying which virtual host matchd the client requested hostname
$match - a scalar containing the hostname sent in the client's SNI TLS extension

Doesn't return anything.

HOWTO: Certificate Transparency

PREREQUISITES

For generating Certificate Transparency files you will need the following:

Certificates

USING THE ct-submit.pl TOOL

Generate one file containing SCTs from all CT log servers

ct-submit.pl --pem server.crt --pem issuer.crt --pem server-CA.pem \
    --extbuf /path/to/CT.sct

The resulted file can be used in your script like:

# set or refresh CT response for a SSL session (default server)
$sv_keys->load_SCT_response('/path/to/CT.sct');

Generate multiple SCT files containing binary representation of the responses received from the log servers

ct-submit.pl --pem server.crt --pem issuer.crt --pem server-CA.pem \
    --individual /path/to/sct/

This will create in the /path/to/stc/ folder the following files (considering that the requests to the log servers were successful):

aviator.sct          # https://ct.googleapis.com/aviator
certly.sct           # https://log.certly.io
pilot.sct            # https://ct.googleapis.com/pilot
rocketeer.sct        # https://ct.googleapis.com/rocketeer
digicert.sct         # https://ct1.digicert-ct.com/log - disabled by default -
                     # accepts certificates only from select CAs
izenpe.sct           # https://ct.izenpe.com - disabled by default -
                     # accepts certificates only from select CAs

One or more files can be used in your script like:

# set or refresh CT response for a SSL session (default server)
# note that even if you're using a single file (which will be wrong
# according to the RFC because at least 2 SCTs from different server logs
# must be sent), you still need to provide an array reference with one element
$sv_keys->load_SCT_response([
        '/path/to/sct/aviator.sct',
        '/path/to/sct/certly.sct'
]);

HOWTO: OCSP staple

PREREQUISITES

For generating an OCSP staple you will need to following:

OpenSSL

OpenSSL with OCSP application installed.

Certificates

GETTING AN OCSP STAPLE

Get the OCSP responder URI

openssl x509 -noout -ocsp_uri -in server.crt

Query the OCSP responder

openssl ocsp -no_nonce -issuer issuer.crt -cert server.crt \
    -CAfile full-CA.crt -url OCSP_responder_URI \
    -header "HOST" OCSP_response_host -respout /path/to/OCSP_staple.der

Inspecting an OCSP staple

openssl ocsp -respin /path/to/OCSP_staple.der -text -CAfile full-CA.crt

USAGE

Set or refresh an OCSP staple to be used within a SSL session (default server)

$sv_keys->load_OCSP_response('/path/to/OCSP_staple.der');

Refreshing an already allocated OCSP staple buffer for a virtual host

Crypt::MatrixSSL3::refresh_OCSP_staple( $erver_index, $index, '/path/to/OCSP_staple.der' );

HOWTO: Virtual hosts

TERMINOLOGY

Default server

Describes a set of properties (certificate, private key, OCSP staple, etc.) to be used when the client connects but doesn't send a SNI TLS extension in its CLIENT_HELLO message.

Virtual host (SNI entry)

Describes also a set of properties (like above) but these will be used when the client sends a SNI extension and we have a successful match on the virtual host's hostname and the client specified hostname.

SNI server

All the virtual hosts (SNI entries) declared for one server.

IMPLEMENTATION

Here is some Perl pseudo code on how these are used:

Crypt::MatrixSSL3::set_VHIndex_callback(sub {
    my ($id, $index) = @_;
    print("Virtual host $index was selected for SSL session $ssl_id");
});

Crypt::MatrixSSL3::set_ALPN_callback(sub {
    my ($id, $app_proto) = @_;
    print("Application protocol $app_proto was negociated for SSL session $ssl_id");
});

my $server_index = -1;

# define a listening socket
$server_sock = ...

# initialize default server keys - these will be shared by all server sessions
my $sv_keys = Crypt::MatrixSSL3::Keys->new();

# load key material (certificate, private key, etc)
$sv_keys->load_rsa(...);

# load OCSP response
$sv_keys->load_OCSP_response(...);

# load SCT response
$sv_keys->load_SCT_response(...);

...

# we assume when a client connects an accept_client sub will be called
sub accept_client {
    # accept client socket
    my $client_sock = accept($server_sock, ...);

    # create server session reusing the keys
    my $cssl =  Crypt::MatrixSSL3::Server->new($sv_keys, undef);

    # create a unique SSL session ID
    # for example this can be the fileno of the client socket
    my $ssl_id = fileno($client_sock);

    # check if the server parameters are initialized
    if ($server_index == -1) {
        # tell the XS module to allocate a new SSL server structure
        $server_index = Crypt::MatrixSSL3::create_SSL_server();

        # set supported protocols for the default server.
        $ssl->set_server_params($server_index, {
            'ALPN' => [...]
        });

        # initialize virtual hosts:
        #   - allocates a SNI_entry structure for each virtual host and:
        #     - creates new server keys
        #     - sets up OCSP staple buffer (server keys - if needed)
        #     - sets up SCT buffer (server keys - if needed)
        #     - stores server implemented protocols if provided
        $ssl->init_SNI($server_index, [
            # see MatrixSSL.pm - init_SNI function
        ]);
    }

    # setup SNI/ALPN callback

    # sets up the matrixSSL SNI callback that will get called if the client sends a SNI TLS extension
    # in its CLIENT_HELLO message. When the XS SNI callback is called if any of the hostnames defined
    # for each virtual host matches againt the client requested hostname, the &VHIndexCallback setup
    # above will be called with the $ssl_id of the session and the 0-based index of the virtual host
    # the client sent its request

    # sets up the matrixSSL ALPN callback that will get called when the client sends an ALPN extension
    # the &ALPNCallback is called with the provided $ssl_id and the selected protocol

    $cssl->set_callbacks($server_index, $sll_id);

    # further initialization stuff after accepting the client
    ...
}

# secure communication with the client
...

SEE ALSO

http://www.MatrixSSL.org - the download from this site includes simple yet comprehensive documentation in PDF format.

SUPPORT

Bugs / Feature Requests

Please report any bugs or feature requests through the issue tracker at https://github.com/powerman/perl-Crypt-MatrixSSL3/issues. You will be notified automatically of any progress on your issue.

Source Code

This is open source software. The code repository is available for public review and contribution under the terms of the license. Feel free to fork the repository and submit pull requests.

https://github.com/powerman/perl-Crypt-MatrixSSL3

git clone https://github.com/powerman/perl-Crypt-MatrixSSL3.git

Resources

AUTHORS

C. N. Drake christopher@pobox.com

Alex Efros powerman@cpan.org

COPYRIGHT AND LICENSE

This software is Copyright (c) 2005- by C. N. Drake christopher@pobox.com.

This software is Copyright (c) 2012- by Alex Efros powerman@cpan.org.

This is free software, licensed under:

The GNU General Public License version 2

MatrixSSL is distributed under the GNU General Public License, Crypt::MatrixSSL3 uses MatrixSSL, and so inherits the same license.