gcry_mpi_invm succeeds if the inverse does not exist

Guido Vranken guidovranken at gmail.com
Sat May 9 13:14:04 CEST 2020


Here is a reproducer for the bugs. OOB reads and writes on i386:

#include <gcrypt.h>

#define CF_CHECK_EQ(expr, res) if ( (expr) != (res) ) { goto end; }

int main(void)
{
    gcry_mpi_t A;
    gcry_mpi_t B;
    gcry_mpi_t C;
    gcry_error_t err;

    CF_CHECK_EQ(err = gcry_mpi_scan(&A, GCRYMPI_FMT_HEX,
"2acc66c62cac3db610ce038e38e391", 0, NULL), 0);
    CF_CHECK_EQ(err = gcry_mpi_scan(&B, GCRYMPI_FMT_HEX,
"4105f5daf47e2dee608c82bbc02a7e5f4f1e6b205e2d099643ad0101ebd11fd3f1182bda60f00000000",
0, NULL), 0);
    CF_CHECK_EQ(err = gcry_mpi_scan(&C, GCRYMPI_FMT_HEX, "1", 0, NULL), 0);
    CF_CHECK_EQ(gcry_mpi_invm(C, A, B), 1);
    printf("Inverse exists\n");
end:

    return 0;
}

Valgrind:

==18960== Invalid read of size 4
==18960==    at 0x1875C0: mpih_invm_pow2 (in
/mnt/2tb/libgcrypt-tmp/libgcrypt/21875/a.out)
==18960==    by 0x187F38: _gcry_mpi_invm (in
/mnt/2tb/libgcrypt-tmp/libgcrypt/21875/a.out)
==18960==    by 0x10D9C4: gcry_mpi_invm (in
/mnt/2tb/libgcrypt-tmp/libgcrypt/21875/a.out)
==18960==    by 0x10CBA7: main (in
/mnt/2tb/libgcrypt-tmp/libgcrypt/21875/a.out)
==18960==  Address 0x4a512d4 is 0 bytes after a block of size 4 alloc'd
==18960==    at 0x483021B: malloc (in
/usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==18960==    by 0x118755: _gcry_private_malloc (in
/mnt/2tb/libgcrypt-tmp/libgcrypt/21875/a.out)
==18960==    by 0x112692: do_malloc (in
/mnt/2tb/libgcrypt-tmp/libgcrypt/21875/a.out)
==18960==    by 0x112711: _gcry_malloc (in
/mnt/2tb/libgcrypt-tmp/libgcrypt/21875/a.out)
==18960==    by 0x112B50: _gcry_xmalloc (in
/mnt/2tb/libgcrypt-tmp/libgcrypt/21875/a.out)
==18960==    by 0x18E35C: _gcry_mpi_alloc_limb_space (in
/mnt/2tb/libgcrypt-tmp/libgcrypt/21875/a.out)
==18960==    by 0x18753B: mpih_invm_pow2 (in
/mnt/2tb/libgcrypt-tmp/libgcrypt/21875/a.out)
==18960==    by 0x187F38: _gcry_mpi_invm (in
/mnt/2tb/libgcrypt-tmp/libgcrypt/21875/a.out)
==18960==    by 0x10D9C4: gcry_mpi_invm (in
/mnt/2tb/libgcrypt-tmp/libgcrypt/21875/a.out)
==18960==    by 0x10CBA7: main (in
/mnt/2tb/libgcrypt-tmp/libgcrypt/21875/a.out)
==18960==
==18960== Invalid write of size 4
==18960==    at 0x1875E0: mpih_invm_pow2 (in
/mnt/2tb/libgcrypt-tmp/libgcrypt/21875/a.out)
==18960==    by 0x187F38: _gcry_mpi_invm (in
/mnt/2tb/libgcrypt-tmp/libgcrypt/21875/a.out)
==18960==    by 0x10D9C4: gcry_mpi_invm (in
/mnt/2tb/libgcrypt-tmp/libgcrypt/21875/a.out)
==18960==    by 0x10CBA7: main (in
/mnt/2tb/libgcrypt-tmp/libgcrypt/21875/a.out)
==18960==  Address 0x4a512d4 is 0 bytes after a block of size 4 alloc'd
==18960==    at 0x483021B: malloc (in
/usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==18960==    by 0x118755: _gcry_private_malloc (in
/mnt/2tb/libgcrypt-tmp/libgcrypt/21875/a.out)
==18960==    by 0x112692: do_malloc (in
/mnt/2tb/libgcrypt-tmp/libgcrypt/21875/a.out)
==18960==    by 0x112711: _gcry_malloc (in
/mnt/2tb/libgcrypt-tmp/libgcrypt/21875/a.out)
==18960==    by 0x112B50: _gcry_xmalloc (in
/mnt/2tb/libgcrypt-tmp/libgcrypt/21875/a.out)
==18960==    by 0x18E35C: _gcry_mpi_alloc_limb_space (in
/mnt/2tb/libgcrypt-tmp/libgcrypt/21875/a.out)
==18960==    by 0x18753B: mpih_invm_pow2 (in
/mnt/2tb/libgcrypt-tmp/libgcrypt/21875/a.out)
==18960==    by 0x187F38: _gcry_mpi_invm (in
/mnt/2tb/libgcrypt-tmp/libgcrypt/21875/a.out)
==18960==    by 0x10D9C4: gcry_mpi_invm (in
/mnt/2tb/libgcrypt-tmp/libgcrypt/21875/a.out)
==18960==    by 0x10CBA7: main (in
/mnt/2tb/libgcrypt-tmp/libgcrypt/21875/a.out)
==18960==
==18960== Invalid read of size 4
==18960==    at 0x187740: mpih_invm_pow2 (in
/mnt/2tb/libgcrypt-tmp/libgcrypt/21875/a.out)
==18960==    by 0x187F38: _gcry_mpi_invm (in
/mnt/2tb/libgcrypt-tmp/libgcrypt/21875/a.out)
==18960==    by 0x10D9C4: gcry_mpi_invm (in
/mnt/2tb/libgcrypt-tmp/libgcrypt/21875/a.out)
==18960==    by 0x10CBA7: main (in
/mnt/2tb/libgcrypt-tmp/libgcrypt/21875/a.out)
==18960==  Address 0x4a51344 is 0 bytes after a block of size 4 alloc'd
==18960==    at 0x483021B: malloc (in
/usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==18960==    by 0x118755: _gcry_private_malloc (in
/mnt/2tb/libgcrypt-tmp/libgcrypt/21875/a.out)
==18960==    by 0x112692: do_malloc (in
/mnt/2tb/libgcrypt-tmp/libgcrypt/21875/a.out)
==18960==    by 0x112711: _gcry_malloc (in
/mnt/2tb/libgcrypt-tmp/libgcrypt/21875/a.out)
==18960==    by 0x112B50: _gcry_xmalloc (in
/mnt/2tb/libgcrypt-tmp/libgcrypt/21875/a.out)
==18960==    by 0x18E35C: _gcry_mpi_alloc_limb_space (in
/mnt/2tb/libgcrypt-tmp/libgcrypt/21875/a.out)
==18960==    by 0x187646: mpih_invm_pow2 (in
/mnt/2tb/libgcrypt-tmp/libgcrypt/21875/a.out)
==18960==    by 0x187F38: _gcry_mpi_invm (in
/mnt/2tb/libgcrypt-tmp/libgcrypt/21875/a.out)
==18960==    by 0x10D9C4: gcry_mpi_invm (in
/mnt/2tb/libgcrypt-tmp/libgcrypt/21875/a.out)
==18960==    by 0x10CBA7: main (in
/mnt/2tb/libgcrypt-tmp/libgcrypt/21875/a.out)
==18960==
==18960== Invalid write of size 4
==18960==    at 0x187760: mpih_invm_pow2 (in
/mnt/2tb/libgcrypt-tmp/libgcrypt/21875/a.out)
==18960==    by 0x187F38: _gcry_mpi_invm (in
/mnt/2tb/libgcrypt-tmp/libgcrypt/21875/a.out)
==18960==    by 0x10D9C4: gcry_mpi_invm (in
/mnt/2tb/libgcrypt-tmp/libgcrypt/21875/a.out)
==18960==    by 0x10CBA7: main (in
/mnt/2tb/libgcrypt-tmp/libgcrypt/21875/a.out)
==18960==  Address 0x4a51344 is 0 bytes after a block of size 4 alloc'd
==18960==    at 0x483021B: malloc (in
/usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==18960==    by 0x118755: _gcry_private_malloc (in
/mnt/2tb/libgcrypt-tmp/libgcrypt/21875/a.out)
==18960==    by 0x112692: do_malloc (in
/mnt/2tb/libgcrypt-tmp/libgcrypt/21875/a.out)
==18960==    by 0x112711: _gcry_malloc (in
/mnt/2tb/libgcrypt-tmp/libgcrypt/21875/a.out)
==18960==    by 0x112B50: _gcry_xmalloc (in
/mnt/2tb/libgcrypt-tmp/libgcrypt/21875/a.out)
==18960==    by 0x18E35C: _gcry_mpi_alloc_limb_space (in
/mnt/2tb/libgcrypt-tmp/libgcrypt/21875/a.out)
==18960==    by 0x187646: mpih_invm_pow2 (in
/mnt/2tb/libgcrypt-tmp/libgcrypt/21875/a.out)
==18960==    by 0x187F38: _gcry_mpi_invm (in
/mnt/2tb/libgcrypt-tmp/libgcrypt/21875/a.out)
==18960==    by 0x10D9C4: gcry_mpi_invm (in
/mnt/2tb/libgcrypt-tmp/libgcrypt/21875/a.out)
==18960==    by 0x10CBA7: main (in
/mnt/2tb/libgcrypt-tmp/libgcrypt/21875/a.out)


On Fri, May 8, 2020 at 6:16 PM Jussi Kivilinna <jussi.kivilinna at iki.fi>
wrote:

> Hello,
>
> On 8.5.2020 1.24, Guido Vranken via Gcrypt-devel wrote:
> > I'm running my crypto library fuzzer on Google OSS-Fuzz and it keeps
> finding bugs in gcry_mpi_invm.
> >
> > jussi kivilinna receives these reports. Would you mind taking a look?
>
> I did see "Issue 21708 in oss-fuzz: cryptofuzz:cryptofuzz-openssl: ASSERT:
> Botan-libgcrypt-BignumCalc-(no algorithm)-difference" 2020-04-15 and
> follow-up discussion and that resulted bug-report to this mailing list. I
> have not seen any further reports from OSS-Fuzz.
>
> If this keeps causing too much noise as repeated bug reports, cannot you
> disable the BigNum fuzzing of libgcrypt until this gets fixed?
>
> -Jussi
>
> >
> > On Tue, Apr 14, 2020 at 8:32 AM NIIBE Yutaka <gniibe at fsij.org <mailto:
> gniibe at fsij.org>> wrote:
> >
> >     Hello,
> >
> >     Thank you for your report with a test case.  It helps a lot.
> >
> >     Guido Vranken wrote:
> >     > This is not in accordance with the documentation:
> >     >
> >     > Function: int gcry_mpi_invm (gcry_mpi_t x, gcry_mpi_t a,
> gcry_mpi_t m)
> >     > Set x to the multiplicative inverse of a \bmod m. Return true if
> the
> >     > inverse exists.
> >
> >     Indeed.  It seems that API was changed to return the result
> >     (success/failure) in libgcrypt 1.3.2 in 2007.  Before that, the API
> was
> >     void (no return value).  Since the initial change, it never returns
> >     correct value.
> >
> >     I'll fix for 1.9.
> >     --
> >
> >
> > _______________________________________________
> > Gcrypt-devel mailing list
> > Gcrypt-devel at gnupg.org
> > http://lists.gnupg.org/mailman/listinfo/gcrypt-devel
> >
>
>
> _______________________________________________
> Gcrypt-devel mailing list
> Gcrypt-devel at gnupg.org
> http://lists.gnupg.org/mailman/listinfo/gcrypt-devel
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.gnupg.org/pipermail/gcrypt-devel/attachments/20200509/ebf7c265/attachment-0001.html>


More information about the Gcrypt-devel mailing list