SHA1_Update() produces wrong results for large buffers

Pavel Gorshkov gorshkov.pavel at gmail.com
Mon Jan 9 16:09:07 PST 2006


An important detail to begin with is that our libmd.a, as opposed
to libmd.so, provides a faster, assembly-optimized version of the
`SHA1_Update' function (it is not compatible with PIC and is
therefore not used in libmd.so).

The problem is that the asm-optimized version fails on large input
buffers.  Attached is a test program, which mmaps a file and then
just feeds its contents to SHA1_Update():

    gcc sha1test.c -o sha1test.md-shared -lmd
    gcc sha1test.c -o sha1test.md-static -lmd -static

the input files:

    dd if=/dev/zero bs=32M count=48 of=test-1.5G
    dd if=/dev/zero bs=32M count=32 of=test-1G
    dd if=/dev/zero bs=32M count=16 of=test-0.5G

***
    # exits immediately, displaying a WRONG hash value
    ./sha1test.md-static test-1.5G
    747cd7172ce7737d1735cf936c0d69ce0f733fcd

    # OK
    ./sha1test.md-shared test-1.5G
    a957f01b1a92366c7b72296cb24eb84f42ed06e4
***
    ./sha1test.md-static test-1G
    0d6ee6083bf8b6368cb80d323e82164e5540e296
    # ^^^ WRONG
    # OK
    ./sha1test.md-shared test-1G
    2a492f15396a6768bcbca016993f4b4c8b0b5307


However, both programs work fine with files less than ~920M:

    ./sha1test.md-static test-0.5G
    5b088492c9f4778f409b7ae61477dec124c99033
    ./sha1test.md-shared test-0.5G
    5b088492c9f4778f409b7ae61477dec124c99033

Everything was tested on a RELENG_6/i386 box (CFLAGS = -O2).

Is this a bug in libmd, or am I missing something?

Thanks in advance,
--
Pavel Gorshkov
-------------- next part --------------
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
#include <sha.h>

int main(int argc, char **argv) {
    int fd;
    struct stat st;
    SHA_CTX ctx;
    unsigned char *buf;
    char hexdigest[41];

    if (argc < 2 || stat(argv[1], &st) < 0 || (fd=open(argv[1], O_RDONLY)) < 0)
	exit(1);
    
    if ((buf = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0)) == MAP_FAILED)
      	exit(1);

    SHA1_Init(&ctx);
    SHA1_Update(&ctx, buf, st.st_size);
    SHA1_End(&ctx, hexdigest);
    puts(hexdigest);

    if (st.st_size)
	munmap(buf, st.st_size);
    close(fd);
    return 0;
}


More information about the freebsd-stable mailing list