mirror of
https://github.com/openssl/openssl.git
synced 2024-11-27 05:21:51 +08:00
Make bntest be (mostly) file-based.
Test suite used from boring, written by David Benjamin. Test driver converted from C++ to C. Added a Perl program to check the testsuite file. Extensive review feedback incorporated (thanks folks). Reviewed-by: Emilia Käsper <emilia@openssl.org> Reviewed-by: Richard Levitte <levitte@openssl.org>
This commit is contained in:
parent
b3618f44a7
commit
8d1ebff41c
2933
test/bntest.c
2933
test/bntest.c
File diff suppressed because it is too large
Load Diff
156
test/bntests.pl
Executable file
156
test/bntests.pl
Executable file
@ -0,0 +1,156 @@
|
||||
#! /usr/bin/env perl
|
||||
# Copyright 2008-2016 The OpenSSL Project Authors. All Rights Reserved.
|
||||
#
|
||||
# Licensed under the OpenSSL license (the "License"). You may not use
|
||||
# this file except in compliance with the License. You can obtain a copy
|
||||
# in the file LICENSE in the source distribution or at
|
||||
# https://www.openssl.org/source/license.html
|
||||
|
||||
# Run the tests specified in bntests.txt, as a check against OpenSSL.
|
||||
use strict;
|
||||
use warnings;
|
||||
use Math::BigInt;
|
||||
|
||||
my $EXPECTED_FAILURES = 0;
|
||||
my $failures = 0;
|
||||
|
||||
sub bn
|
||||
{
|
||||
my $x = shift;
|
||||
my ($sign, $hex) = ($x =~ /^([+\-]?)(.*)$/);
|
||||
|
||||
$hex = '0x' . $hex if $hex !~ /^0x/;
|
||||
return Math::BigInt->from_hex($sign.$hex);
|
||||
}
|
||||
|
||||
sub evaluate
|
||||
{
|
||||
my $lineno = shift;
|
||||
my %s = @_;
|
||||
|
||||
if ( defined $s{'Sum'} ) {
|
||||
# Sum = A + B
|
||||
my $sum = bn($s{'Sum'});
|
||||
my $a = bn($s{'A'});
|
||||
my $b = bn($s{'B'});
|
||||
return if $sum == $a + $b;
|
||||
} elsif ( defined $s{'LShift1'} ) {
|
||||
# LShift1 = A * 2
|
||||
my $lshift1 = bn($s{'LShift1'});
|
||||
my $a = bn($s{'A'});
|
||||
return if $lshift1 == $a->bmul(2);
|
||||
} elsif ( defined $s{'LShift'} ) {
|
||||
# LShift = A * 2**N
|
||||
my $lshift = bn($s{'LShift'});
|
||||
my $a = bn($s{'A'});
|
||||
my $n = bn($s{'N'});
|
||||
return if $lshift == $a->blsft($n);
|
||||
} elsif ( defined $s{'RShift'} ) {
|
||||
# RShift = A / 2**N
|
||||
my $rshift = bn($s{'RShift'});
|
||||
my $a = bn($s{'A'});
|
||||
my $n = bn($s{'N'});
|
||||
return if $rshift == $a->brsft($n);
|
||||
} elsif ( defined $s{'Square'} ) {
|
||||
# Square = A * A
|
||||
my $square = bn($s{'Square'});
|
||||
my $a = bn($s{'A'});
|
||||
return if $square == $a->bmul($a);
|
||||
} elsif ( defined $s{'Product'} ) {
|
||||
# Product = A * B
|
||||
my $product = bn($s{'Product'});
|
||||
my $a = bn($s{'A'});
|
||||
my $b = bn($s{'B'});
|
||||
return if $product == $a->bmul($b);
|
||||
} elsif ( defined $s{'Quotient'} ) {
|
||||
# Quotient = A / B
|
||||
# Remainder = A - B * Quotient
|
||||
my $quotient = bn($s{'Quotient'});
|
||||
my $remainder = bn($s{'Remainder'});
|
||||
my $a = bn($s{'A'});
|
||||
my $b = bn($s{'B'});
|
||||
|
||||
# First the remainder test.
|
||||
$b->bmul($quotient);
|
||||
my $rempassed = $remainder == $a->bsub($b) ? 1 : 0;
|
||||
|
||||
# Math::BigInt->bdiv() is documented to do floored division,
|
||||
# i.e. 1 / -4 = -1, while OpenSSL BN_div does truncated
|
||||
# division, i.e. 1 / -4 = 0. We need to make the operation
|
||||
# work like OpenSSL's BN_div to be able to verify.
|
||||
$a = bn($s{'A'});
|
||||
$b = bn($s{'B'});
|
||||
my $neg = $a->is_neg() ? !$b->is_neg() : $b->is_neg();
|
||||
$a->babs();
|
||||
$b->babs();
|
||||
$a->bdiv($b);
|
||||
$a->bneg() if $neg;
|
||||
return if $rempassed && $quotient == $a;
|
||||
} elsif ( defined $s{'ModMul'} ) {
|
||||
# ModMul = (A * B) mod M
|
||||
my $modmul = bn($s{'ModMul'});
|
||||
my $a = bn($s{'A'});
|
||||
my $b = bn($s{'B'});
|
||||
my $m = bn($s{'M'});
|
||||
$a->bmul($b);
|
||||
return if $modmul == $a->bmod($m);
|
||||
} elsif ( defined $s{'ModExp'} ) {
|
||||
# ModExp = (A ** E) mod M
|
||||
my $modexp = bn($s{'ModExp'});
|
||||
my $a = bn($s{'A'});
|
||||
my $e = bn($s{'E'});
|
||||
my $m = bn($s{'M'});
|
||||
return if $modexp == $a->bmodpow($e, $m);
|
||||
} elsif ( defined $s{'Exp'} ) {
|
||||
my $exp = bn($s{'Exp'});
|
||||
my $a = bn($s{'A'});
|
||||
my $e = bn($s{'E'});
|
||||
return if $exp == $a ** $e;
|
||||
} elsif ( defined $s{'ModSqrt'} ) {
|
||||
# (ModSqrt * ModSqrt) mod P = A mod P
|
||||
my $modsqrt = bn($s{'ModSqrt'});
|
||||
my $a = bn($s{'A'});
|
||||
my $p = bn($s{'P'});
|
||||
$modsqrt->bmul($modsqrt);
|
||||
$modsqrt->bmod($p);
|
||||
$a->bmod($p);
|
||||
return if $modsqrt == $a;
|
||||
} else {
|
||||
print "# Unknown test: ";
|
||||
}
|
||||
$failures++;
|
||||
print "# #$failures Test (before line $lineno) failed\n";
|
||||
foreach ( keys %s ) {
|
||||
print "$_ = $s{$_}\n";
|
||||
}
|
||||
print "\n";
|
||||
}
|
||||
|
||||
my $infile = shift || 'bntests.txt';
|
||||
die "No such file, $infile" unless -f $infile;
|
||||
open my $IN, $infile || die "Can't read $infile, $!\n";
|
||||
|
||||
my %stanza = ();
|
||||
my $l = 0;
|
||||
while ( <$IN> ) {
|
||||
$l++;
|
||||
s|\R$||;
|
||||
next if /^#/;
|
||||
if ( /^$/ ) {
|
||||
if ( keys %stanza ) {
|
||||
evaluate($l, %stanza);
|
||||
%stanza = ();
|
||||
}
|
||||
next;
|
||||
}
|
||||
# Parse 'key = value'
|
||||
if ( ! /\s*([^\s]*)\s*=\s*(.*)\s*/ ) {
|
||||
print "Skipping $_\n";
|
||||
next;
|
||||
}
|
||||
$stanza{$1} = $2;
|
||||
};
|
||||
evaluate($l, %stanza) if keys %stanza;
|
||||
die "Got $failures, expected $EXPECTED_FAILURES"
|
||||
if $infile eq 'bntests.txt' and $failures != $EXPECTED_FAILURES;
|
||||
close($IN)
|
10538
test/bntests.txt
Normal file
10538
test/bntests.txt
Normal file
File diff suppressed because it is too large
Load Diff
@ -35,7 +35,7 @@ IF[{- !$disabled{tests} -}]
|
||||
INCLUDE[sanitytest]=../include
|
||||
DEPEND[sanitytest]=../libcrypto
|
||||
|
||||
SOURCE[bntest]=bntest.c
|
||||
SOURCE[bntest]=bntest.c testutil.c test_main_custom.c
|
||||
INCLUDE[bntest]=.. ../crypto/include ../include
|
||||
DEPEND[bntest]=../libcrypto
|
||||
|
||||
|
@ -16,69 +16,7 @@ use OpenSSL::Test qw/:DEFAULT srctop_file/;
|
||||
|
||||
setup("test_bn");
|
||||
|
||||
plan tests => 3;
|
||||
plan tests => 1;
|
||||
|
||||
require_ok(srctop_file("test","recipes","bc.pl"));
|
||||
|
||||
my $testresults = "tmp.bntest";
|
||||
my $init = ok(run(test(["bntest"], stdout => $testresults)), 'initialize');
|
||||
|
||||
SKIP: {
|
||||
skip "Initializing failed, skipping", 1 if !$init;
|
||||
|
||||
subtest 'Checking the bn results' => sub {
|
||||
my @lines = ();
|
||||
if (open DATA, $testresults) {
|
||||
@lines = <DATA>;
|
||||
close DATA;
|
||||
}
|
||||
map { s/\R//; } @lines; # chomp(@lines);
|
||||
|
||||
plan tests => scalar grep(/^print /, @lines);
|
||||
|
||||
my $l = "";
|
||||
|
||||
while (scalar @lines) {
|
||||
$l = shift @lines;
|
||||
|
||||
last if $l =~ /^print /;
|
||||
}
|
||||
|
||||
while (1) {
|
||||
$l =~ s/^print "//;
|
||||
$l =~ s/\\n"//;
|
||||
my $t = $l;
|
||||
my @operations = ();
|
||||
|
||||
$l = undef;
|
||||
while (scalar @lines) {
|
||||
$l = shift @lines;
|
||||
|
||||
last if $l =~ /^print /;
|
||||
push @operations, $l;
|
||||
$l = undef;
|
||||
}
|
||||
|
||||
ok(check_operations(@operations), "verify $t");
|
||||
|
||||
last unless $l;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
unlink $testresults;
|
||||
|
||||
sub check_operations {
|
||||
my $failcount = 0;
|
||||
|
||||
foreach my $line (@_) {
|
||||
my $result = calc(split /\s+/, $line);
|
||||
|
||||
if ($result ne "0" && $result ne "0x0") {
|
||||
$failcount++;
|
||||
print STDERR "Failed! $line => $result\n";
|
||||
}
|
||||
}
|
||||
|
||||
return $failcount == 0;
|
||||
}
|
||||
ok(run(test(["bntest", srctop_file("test", "bntests.txt")])),
|
||||
"running bntest bntests.txt");
|
||||
|
@ -1,113 +0,0 @@
|
||||
#! /usr/bin/env perl
|
||||
# Copyright 2015-2016 The OpenSSL Project Authors. All Rights Reserved.
|
||||
#
|
||||
# Licensed under the OpenSSL license (the "License"). You may not use
|
||||
# this file except in compliance with the License. You can obtain a copy
|
||||
# in the file LICENSE in the source distribution or at
|
||||
# https://www.openssl.org/source/license.html
|
||||
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use Math::BigInt;
|
||||
|
||||
sub calc {
|
||||
@_ = __adder(@_);
|
||||
if (scalar @_ != 1) { return "NaN"; }
|
||||
return shift;
|
||||
}
|
||||
|
||||
sub __canonhex {
|
||||
my ($sign, $hex) = (shift =~ /^([+\-]?)(.*)$/);
|
||||
$hex = "0x".$hex if $hex !~ /^0x/;
|
||||
return $sign.$hex;
|
||||
}
|
||||
|
||||
sub __adder {
|
||||
@_ = __multiplier(@_);
|
||||
while (scalar @_ > 1 && $_[1] =~ /^[\+\-]$/) {
|
||||
my $operand1 = Math::BigInt->from_hex(__canonhex(shift));
|
||||
my $operator = shift;
|
||||
@_ = __multiplier(@_);
|
||||
my $operand2 = Math::BigInt->from_hex(__canonhex(shift));
|
||||
if ($operator eq "+") {
|
||||
$operand1->badd($operand2);
|
||||
} elsif ($operator eq "-") {
|
||||
$operand1->bsub($operand2);
|
||||
} else {
|
||||
die "SOMETHING WENT AWFULLY WRONG";
|
||||
}
|
||||
unshift @_, $operand1->as_hex();
|
||||
}
|
||||
return @_;
|
||||
}
|
||||
|
||||
sub __multiplier {
|
||||
@_ = __power(@_);
|
||||
while (scalar @_ > 1 && $_[1] =~ /^[\*\/%]$/) {
|
||||
my $operand1 = Math::BigInt->from_hex(__canonhex(shift));
|
||||
my $operator = shift;
|
||||
@_ = __power(@_);
|
||||
my $operand2 = Math::BigInt->from_hex(__canonhex(shift));
|
||||
if ($operator eq "*") {
|
||||
$operand1->bmul($operand2);
|
||||
} elsif ($operator eq "/") {
|
||||
# Math::BigInt->bdiv() is documented to do floored division,
|
||||
# i.e. 1 / -4 = -1, while bc and OpenSSL BN_div do truncated
|
||||
# division, i.e. 1 / -4 = 0. We need to make the operation
|
||||
# work like OpenSSL's BN_div to be able to verify.
|
||||
my $neg = ($operand1->is_neg()
|
||||
? !$operand2->is_neg() : $operand2->is_neg());
|
||||
$operand1->babs();
|
||||
$operand2->babs();
|
||||
$operand1->bdiv($operand2);
|
||||
if ($neg) { $operand1->bneg(); }
|
||||
} elsif ($operator eq "%") {
|
||||
# Here's a bit of a quirk...
|
||||
# With OpenSSL's BN, as well as bc, the result of -10 % 3 is -1
|
||||
# while Math::BigInt, the result is 2.
|
||||
# The latter is mathematically more correct, but...
|
||||
my $o1isneg = $operand1->is_neg();
|
||||
$operand1->babs();
|
||||
# Math::BigInt does something different with a negative modulus,
|
||||
# while OpenSSL's BN and bc treat it like a positive number...
|
||||
$operand2->babs();
|
||||
$operand1->bmod($operand2);
|
||||
if ($o1isneg) { $operand1->bneg(); }
|
||||
} else {
|
||||
die "SOMETHING WENT AWFULLY WRONG";
|
||||
}
|
||||
unshift @_, $operand1->as_hex();
|
||||
}
|
||||
return @_;
|
||||
}
|
||||
|
||||
sub __power {
|
||||
@_ = __paren(@_);
|
||||
while (scalar @_ > 1 && $_[1] eq "^") {
|
||||
my $operand1 = Math::BigInt->from_hex(__canonhex(shift));
|
||||
shift;
|
||||
@_ = __paren(@_);
|
||||
my $operand2 = Math::BigInt->from_hex(__canonhex(shift));
|
||||
$operand1->bpow($operand2);
|
||||
unshift @_, $operand1->as_hex();
|
||||
}
|
||||
return @_;
|
||||
}
|
||||
|
||||
# returns array ( $result, @remaining )
|
||||
sub __paren {
|
||||
if (scalar @_ > 0 && $_[0] eq "(") {
|
||||
shift;
|
||||
my @result = __adder(@_);
|
||||
if (scalar @_ == 0 || $_[0] ne ")") {
|
||||
return ("NaN");
|
||||
}
|
||||
shift;
|
||||
return @result;
|
||||
}
|
||||
return @_;
|
||||
}
|
||||
|
||||
1;
|
Loading…
Reference in New Issue
Block a user