Crypt-OpenSSL-PKCS12
view release on metacpan or search on metacpan
t/pkcs12-info-cve-2026-8507.t view on Meta::CPAN
# Integer overflow in print_attribute (V_ASN1_OCTET_STRING / V_ASN1_BIT_STRING)
# leading to heap out-of-bounds write.
#
# The fix bounds-checks ASN1_STRING.length before the *4 multiplication and
# promotes to size_t. This test exercises the fixed code path by calling
# info() and info_as_hash() on a PKCS12 that carries OCTET STRING bag
# attributes (localKeyID), confirming normal processing still works and that
# the returned hex strings are intact.
#
# Note: directly triggering the croak for lengths > INT_MAX/4 would require a
# specially crafted binary PKCS12 fixture with a ~512 MiB attribute field and
# is not included here.
use strict;
use warnings;
use Test::More tests => 8;
use File::Spec::Functions qw(:ALL);
use Crypt::OpenSSL::Guess qw(openssl_version);
BEGIN { use_ok('Crypt::OpenSSL::PKCS12') }
my ($major) = openssl_version();
# test.pfx contains localKeyID (OCTET STRING) bag attributes â the exact
# type whose length*4 multiplication overflowed before the fix.
my $pkcs12 = Crypt::OpenSSL::PKCS12->new_from_file(catdir('certs', 'test.pfx'));
ok($pkcs12, 'PKCS12 object loaded from test.pfx');
my $pass = '1234';
# info() exercises the BIO/string output path of print_attribute
my $info = eval { $pkcs12->info($pass) };
is($@, '', 'info() does not croak on OCTET STRING bag attributes');
ok(defined $info && length $info, 'info() returns non-empty string');
# localKeyID is rendered as hex by get_hex() via the OCTET STRING branch â
# confirm the output is present and well-formed.
like($info, qr/localKeyID:?\s+[0-9A-F]{2}/i,
'info() output contains hex-encoded localKeyID attribute');
# info_as_hash() exercises the hash-population path of the same code
my $hash = eval { $pkcs12->info_as_hash($pass) };
is($@, '', 'info_as_hash() does not croak on OCTET STRING bag attributes');
ok(defined $hash && ref $hash eq 'HASH', 'info_as_hash() returns a hash reference');
SKIP: {
skip('pkcs7_data not present or empty', 1)
unless ref $hash->{pkcs7_data} eq 'ARRAY' && @{$hash->{pkcs7_data}};
my $found_localKeyID = 0;
for my $section (@{$hash->{pkcs7_data}}) {
for my $bag (@{$section->{bags} // []}) {
if (exists $bag->{bag_attributes}{localKeyID}) {
$found_localKeyID = 1;
last;
}
}
last if $found_localKeyID;
}
ok($found_localKeyID, 'info_as_hash() correctly decoded localKeyID OCTET STRING attribute');
}
( run in 1.159 second using v1.01-cache-2.11-cpan-600a1bdf6e4 )