Add unit tests for the new function mbedtls_mpi_core_add_if() in bignum_new.c

The test cases use the following MPI values.

The .data file only includes those (a, b) values where a <= b, and gives the
sum unconditionally; the test code exercises a >= b and cond == 0 using these
values. The .data file gives two values for the carry out, which are for when
sizeof(mbedtls_mpi_uint) == 4 or 8.

    0 1 3 f fe ff 100 ff00 fffe ffff 10000
    fffffffe ffffffff 100000000 1f7f7f7f7f7f7f
    8000000000000000 fefefefefefefefe fffffffffffffffe ffffffffffffffff
    10000000000000000 1234567890abcdef0
    fffffffffffffffffefefefefefefefe fffffffffffffffffffffffffffffffe
    ffffffffffffffffffffffffffffffff 100000000000000000000000000000000
    1234567890abcdef01234567890abcdef0
    fffffffffffffffffffffffffffffffffffffffffffffffffefefefefefefefe
    fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe
    ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
    10000000000000000000000000000000000000000000000000000000000000000
    1234567890abcdef01234567890abcdef01234567890abcdef01234567890abcdef0
    4df72d07b4b71c8dacb6cffa954f8d88254b6277099308baf003fab73227f34029643b5a263f66e0d3c3fa297ef71755efd53b8fb6cb812c6bbf7bcf179298bd9947c4c8b14324140a2c0f5fad7958a69050a987a6096e9f055fb38edf0c5889eca4a0cfa99b45fbdeee4c696b328ddceae4723945901ec025076b12b

The lines in the .data file were generated by the following script

```
    #!/usr/bin/env perl
    #
    # mpi-test-core-add-if.pl - generate MPI tests in Perl for mbedtls_mpi_core_add_if()
    #
    use strict;
    use warnings;
    use Math::BigInt;
    use sort 'stable';

    my @add_mpis = qw(
        0 1 3 f fe ff 100 ff00 fffe ffff 10000
        fffffffe ffffffff 100000000 1f7f7f7f7f7f7f
        8000000000000000 fefefefefefefefe fffffffffffffffe ffffffffffffffff
        10000000000000000 1234567890abcdef0
        fffffffffffffffffefefefefefefefe fffffffffffffffffffffffffffffffe ffffffffffffffffffffffffffffffff
        100000000000000000000000000000000 1234567890abcdef01234567890abcdef0
        fffffffffffffffffffffffffffffffffffffffffffffffffefefefefefefefe
        fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe
        ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
        10000000000000000000000000000000000000000000000000000000000000000
        1234567890abcdef01234567890abcdef01234567890abcdef01234567890abcdef0
        4df72d07b4b71c8dacb6cffa954f8d88254b6277099308baf003fab73227f34029643b5a263f66e0d3c3fa297ef71755efd53b8fb6cb812c6bbf7bcf179298bd9947c4c8b14324140a2c0f5fad7958a69050a987a6096e9f055fb38edf0c5889eca4a0cfa99b45fbdeee4c696b328ddceae4723945901ec025076b12b
    );

    generate_tests();

    sub generate_tests {
        generate_mbedtls_mpi_core_add_if();
    }

    sub generate_mbedtls_mpi_core_add_if {

        my $sub_name = (caller(0))[3];      # e.g. main::generate_mbedtls_mpi_add_mpi
        my ($ignore, $test_name) = split("main::generate_", $sub_name);

        my @cases = ();

        for my $ah (@add_mpis) {
            for my $bh (@add_mpis) {

                my $a = Math::BigInt->from_hex($ah);
                my $b = Math::BigInt->from_hex($bh);
                next if $a > $b;                # don't need to repeat test cases

                # $b is the larger (or equal) of the two numbers. That's the number of limbs
                # we'll be using.
                my $bound4 = bound_mpi4($b);
                my $bound8 = bound_mpi8($b);

                my $r = $a + $b;
                my ($r4, $carry4) = ($r->copy(), 0);
                my ($r8, $carry8) = ($r->copy(), 0);

                ($carry4, $r4) = $r4->bdiv($bound4);
                ($carry8, $r8) = $r8->bdiv($bound8);

                my $rh4 = $r4->to_hex();
                my $rh8 = $r8->to_hex();

                my $desc = "$test_name #NUMBER: 0x$ah + 0x$bh = (0x$rh4, carry $carry4)/(0x$rh8, carry $carry8)EXPLAIN";
                my $case = output($test_name, str($ah), str($bh), str($rh4), $carry4, str($rh8), $carry8);

                push(@cases, [$case, $desc]);
            }
        }

        output_cases(" (for when sizeof(mbedtls_mpi_uint) == 4/8)", @cases);
    }

    sub output_cases {

        my ($explain, @cases) = @_;

        my $count = 1;
        for my $c (@cases) {

            my ($case, $desc, $dep) = @$c;
            $desc =~ s/NUMBER/$count/; $count++;
            if (defined($explain) && $desc =~ /EXPLAIN/) {
                $desc =~ s/EXPLAIN/$explain/;
                $explain = "";
            }

            my $depends = "";
            $depends = "depends_on:$dep\n" if defined($dep) && length($dep);

            print <<EOF;

    $desc
    $depends$case
    EOF
        }
    }

    # The first number (a power of 2) that won't fit in the number of MPIs
    # needed for the given number
    sub bound_mpi4 {
        my $one = Math::BigInt->new(1);     # blsft modifies caller
        return $one->blsft(bits_mpi4($_[0]));
    }

    sub bound_mpi8 {
        my $one = Math::BigInt->new(1);     # blsft modifies caller
        return $one->blsft(bits_mpi8($_[0]));
    }

    # How many bits (a multiple of 32) needed to store the specified number
    # when using 4-byte MPIs
    sub bits_mpi4 {
        return 32 * mpi4s($_[0]);
    }

    # How many bits (a multiple of 64) needed to store the specified number
    # when using 8-byte MPIs
    sub bits_mpi8 {
        return 64 * mpi8s($_[0]);
    }

    # How many 4-byte MPIs needed to store the specified number
    sub mpi4s {
        my ($n) = @_;
        my $h = $n->to_hex();
        return int((length($h) + 7) / 8);
    }

    # How many 8-byte MPIs needed to store the specified number
    sub mpi8s {
        my ($n) = @_;
        my $h = $n->to_hex();
        return int((length($h) + 15) / 16);
    }

    sub output {
        return join(":", @_);
    }

    sub str {
        return '"' . $_[0] . '"';
    }
```

Signed-off-by: Tom Cosgrove <tom.cosgrove@arm.com>
This commit is contained in:
Tom Cosgrove 2022-08-23 16:26:52 +01:00
parent 268f96b0ef
commit 0cc78658c3
2 changed files with 1678 additions and 0 deletions

File diff suppressed because it is too large Load Diff

View File

@ -1720,6 +1720,100 @@ exit:
}
/* END_CASE */
/* BEGIN_CASE */
void mbedtls_mpi_core_add_if( char * input_l, char * input_r,
char * input_X4, int carry4,
char * input_X8, int carry8 )
{
mbedtls_mpi X4, X8, l, r;
mbedtls_mpi_uint *la = NULL;
mbedtls_mpi_uint *ra = NULL;
mbedtls_mpi_uint *Xa = NULL;
mbedtls_mpi_uint *da = NULL;
mbedtls_mpi_init( &X4 );
mbedtls_mpi_init( &X8 );
mbedtls_mpi_init( &l );
mbedtls_mpi_init( &r );
TEST_EQUAL( mbedtls_test_read_mpi( &l, input_l ), 0 );
TEST_EQUAL( mbedtls_test_read_mpi( &r, input_r ), 0 );
TEST_EQUAL( mbedtls_test_read_mpi( &X4, input_X4 ), 0 );
TEST_EQUAL( mbedtls_test_read_mpi( &X8, input_X8 ), 0 );
/* We only need to work with one of (X4, carry4) or (X8, carry8) depending
* on sizeof(mbedtls_mpi_uint)
*/
mbedtls_mpi *X = ( sizeof(mbedtls_mpi_uint) == 4 ) ? &X4 : &X8;
mbedtls_mpi_uint carry = ( sizeof(mbedtls_mpi_uint) == 4 ) ? carry4 : carry8;
/* All of the inputs are +ve (or zero) */
TEST_EQUAL( l.s, 1 );
TEST_EQUAL( r.s, 1 );
TEST_EQUAL( X->s, 1 );
/* Test cases are such that l <= r, so #limbs should be <= */
TEST_ASSERT( l.n <= r.n );
TEST_ASSERT( X->n <= r.n );
/* Now let's get arrays of mbedtls_mpi_uints, rather than MPI structures */
la = mbedtls_calloc( r.n, sizeof(mbedtls_mpi_uint) );
ra = mbedtls_calloc( r.n, sizeof(mbedtls_mpi_uint) );
Xa = mbedtls_calloc( r.n, sizeof(mbedtls_mpi_uint) );
da = mbedtls_calloc( r.n, sizeof(mbedtls_mpi_uint) );
TEST_ASSERT( la != NULL );
TEST_ASSERT( ra != NULL );
TEST_ASSERT( Xa != NULL );
TEST_ASSERT( da != NULL );
/* Populate the arrays. As the mbedtls_mpi_uint[]s in mbedtls_mpis (and as
* processed by mbedtls_mpi_core_add_if()) are little endian, we can just
* copy what we have as long as MSBs are 0 (which they are from calloc())
*/
memcpy( la, l.p, l.n * sizeof(mbedtls_mpi_uint) );
memcpy( ra, r.p, r.n * sizeof(mbedtls_mpi_uint) );
memcpy( Xa, X->p, X->n * sizeof(mbedtls_mpi_uint) );
/* 1a) a += b, cond = 0 => there should be no carry */
memcpy( da, la, r.n * sizeof(mbedtls_mpi_uint) );
TEST_EQUAL( mbedtls_mpi_core_add_if( da, ra, r.n, 0 ), 0 );
/* 1b) and a should be unchanged */
TEST_EQUAL( memcmp( da, la, r.n * sizeof(mbedtls_mpi_uint) ), 0 );
/* 2a) a += b, cond = 1 => we should get the correct carry */
TEST_EQUAL( mbedtls_mpi_core_add_if( da, ra, r.n, 1 ), carry );
/* 2b) and a should have the correct result */
TEST_EQUAL( memcmp( da, Xa, r.n * sizeof(mbedtls_mpi_uint) ), 0 );
/* 3a) b += a, cond = 0 => there should be no carry */
memcpy( da, ra, r.n * sizeof(mbedtls_mpi_uint) );
TEST_EQUAL( mbedtls_mpi_core_add_if( da, la, r.n, 0 ), 0 );
/* 3b) and b should be unchanged */
TEST_EQUAL( memcmp( da, ra, r.n * sizeof(mbedtls_mpi_uint) ), 0 );
/* 4a) b += a, cond = 1 => we should get the correct carry */
TEST_EQUAL( mbedtls_mpi_core_add_if( da, la, r.n, 1 ), carry );
/* 4b) and b should have the correct result */
TEST_EQUAL( memcmp( da, Xa, r.n * sizeof(mbedtls_mpi_uint) ), 0 );
exit:
mbedtls_free( la );
mbedtls_free( ra );
mbedtls_free( Xa );
mbedtls_free( da );
mbedtls_mpi_free( &X4 );
mbedtls_mpi_free( &X8 );
mbedtls_mpi_free( &l );
mbedtls_mpi_free( &r );
}
/* END_CASE */
/* BEGIN_CASE depends_on:MBEDTLS_SELF_TEST */
void mpi_selftest( )
{