Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions RSA.pm
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,8 @@ sub get_key_parameters {

*get_public_key_pkcs1_string = \&get_public_key_string;

sub CLONE_SKIP { 1 }

unless ( defined &use_sslv23_padding ) {
*use_sslv23_padding = sub {
croak( "use_sslv23_padding is not available: "
Expand Down Expand Up @@ -487,6 +489,15 @@ Return true if this is a private key, and false if it is public only.

=back

=head1 THREAD SAFETY

This module defines C<CLONE_SKIP>, which means that
C<Crypt::OpenSSL::RSA> objects become undefined in child threads
created via C<threads-E<gt>create()>. Each thread must construct its
own key objects. This prevents double-free crashes that would
otherwise occur when both parent and child threads destroy the same
underlying OpenSSL key structure.

=head1 AUTHOR

Ian Robertson, C<iroberts@cpan.org>. For support, please email
Expand Down
41 changes: 41 additions & 0 deletions t/threads.t
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
use strict;
use warnings;
use Test::More;
use Config;

BEGIN {
if (!$Config{useithreads}) {
plan skip_all => 'perl not built with ithreads';
}
eval 'require threads; threads->import()';
if ($@) {
plan skip_all => "threads not available: $@";
}
}
use Crypt::OpenSSL::Random;
use Crypt::OpenSSL::RSA;

plan tests => 4;

Crypt::OpenSSL::Random::random_seed("OpenSSL needs at least 32 bytes.");
Crypt::OpenSSL::RSA->import_random_seed();

ok(Crypt::OpenSSL::RSA->can('CLONE_SKIP'),
"CLONE_SKIP is defined");
is(Crypt::OpenSSL::RSA->CLONE_SKIP, 1,
"CLONE_SKIP returns 1");

my $rsa = Crypt::OpenSSL::RSA->generate_key(2048);
my $pub_pem = $rsa->get_public_key_x509_string();

my $thr = threads->create(sub {
my $child_rsa = Crypt::OpenSSL::RSA->generate_key(2048);
return $child_rsa->get_public_key_x509_string();
});

my $child_pub = $thr->join();
ok(defined $child_pub && $child_pub =~ /^-----BEGIN PUBLIC KEY-----/,
"child thread can independently generate and export keys");

ok($rsa->get_public_key_x509_string() eq $pub_pem,
"parent RSA object undamaged after child thread exit");
Loading