package Crypt::OpenSSL::Common;

use 5.008008;
use strict;
use warnings;

our $VERSION = '0.1';

require Exporter;
our @EXPORT = qw();
our @EXPORT_OK = qw(get_error error_string version version_atbuild);
our %EXPORT_TAGS = (
    all => [@EXPORT_OK]
);
*export = \&Exporter::export;

sub import {
    load_crypto_strings();
    Exporter::export_to_level(__PACKAGE__, 1, @_);
}

# A missing C::O::RSA method
sub Crypt::OpenSSL::RSA::new_from_file {
    my($proto, $file) = @_;
    open(my $pkfh, '<', $file) or die "Can't open key file: $!\n";
    local $/ = undef;
    return $proto->new_private_key(<$pkfh>);
}

require XSLoader;
XSLoader::load('Crypt::OpenSSL::Common', $VERSION);

1;
__END__

=head1 NAME

Crypt::OpenSSL::Common - Common services from the OpenSSL libraries.

=head1 SYNOPSIS

    use Crypt::OpenSSL::Foo;
    use Crypt::OpenSSL::Common;

    # Now use the functionality of Crypt::OpenSSL::Foo as usual.

=head1 INTRODUCTION

There are in CPAN a lot of modules that provides bindings to many parts of the
OpenSSL libraries. Among them:

    Crypt::OpenSSL::RSA     OpenSSL's RSA API
    Crypt::OpenSSL::X509    OpenSSL's X509 API
    Crypt::OpenSSL::PKCS10  PKCS#10 creation and handling
    Crypt::OpenSSL::Bignum  Multiprecision integer arithmetic (OpenSSL "bn" library)

But the OpenSSL libraries provides a few common functions that are global in nature,
for example, all the C<ERR_*> handling functions or the C<SSL_library_init> function.

The main purpose of this module is to provides perl bindings to all those functions.

=head1 DESCRIPTION

    use Crypt::OpenSSL::Common;
    # now 'use' other OpenSSL modules

The first time that your program uses this module, the OpenSSL is properly initialized.
This initialization loads from the library all the available cryptographic algorithms.

The main visible effect is that some other APIs can now automatically recognize them.

For example, the Crypt::OpenSSL::RSA's new_private_key class method now can handle
I<encrypted> private keys in the same way the C API does, ie. prompting the user for
the I<pass phrase> used to protect the private key.

This initialization can't be properly done in any one of the individual modules.

=head1 INTERFACE

=head2 Functions

None of the following are exported by default.

=over 4

=item version()

Returns the loaded OpenSSL library version number.

=item version_atbuild()

Returns the OpenSSL library version used to build the module. It can be different
to L<version> above.

=item get_error()

Returns the numeric code of the last error generated by an OpenSSL's API call.

=item error_string(B<code>)

Returns a human readable string from the error code B<code>.

=back

=head2 Extentions

This module provides some methods that I consider missing from other modules of the
family.

=over 4

=item Crypt::OpenSSL::RSA->new_from_file(B<$filename>)

Returns a new L<Crypt::OpenSSL::RSA> object from the PEM encoded file B<$filename>.

=back

If you maintains any of the modules mentioned, fell free to adopt de missing
functionality and when doing so, please drop me a note.

=head1 AUTHOR

Salvador Ortiz <sortiz@cpan.org>

=head1 SEE ALSO

L<perl(1)>, L<ssl(3)>, L<err(3ssl)>

=begin PRIVATE

=head1 PRIVATE INTERFACE

=over 4

=item load_crypto_string()

Calls the L<ERR_load_crypto_string(3)> function.

=back

=end PRIVATE
