Message ID | 20210709025313.674287-7-stefanb@linux.vnet.ibm.com |
---|---|
State | Superseded |
Headers | show |
Series | tcgbios: Use the proper hashes for the TPM 2 PCR banks | expand |
On 09/07/2021 12:53, Stefan Berger wrote: > From: Stefan Berger <stefanb@linux.ibm.com> > > Add test cases for sha1, sha256, sha384, and sha512 and a test script > to run the test cases. > > Signed-off-by: Stefan Berger <stefanb@linux.ibm.com> > --- > lib/libtpm/sha.c | 26 +++++++++++++++++++ > lib/libtpm/sha256.c | 25 +++++++++++++++++++ > lib/libtpm/sha512.c | 32 ++++++++++++++++++++++++ > lib/libtpm/sha_test.h | 58 +++++++++++++++++++++++++++++++++++++++++++ > lib/libtpm/test.sh | 29 ++++++++++++++++++++++ > 5 files changed, 170 insertions(+) > create mode 100644 lib/libtpm/sha_test.h > create mode 100755 lib/libtpm/test.sh > > diff --git a/lib/libtpm/sha.c b/lib/libtpm/sha.c > index 43de658..6e8b19b 100644 > --- a/lib/libtpm/sha.c > +++ b/lib/libtpm/sha.c > @@ -203,3 +203,29 @@ void sha1(const uint8_t *data, uint32_t length, uint8_t *hash) > sha1_do(&ctx, data, length); > memcpy(hash, &ctx.h[0], 20); > } > + > +#ifdef MAIN > + > +#include "sha_test.h" > + > +int main(void) > +{ > + TESTVECTORS(data); > + uint8_t hash[20]; > + char input[64]; > + int err = 0; > + size_t i; > + > + for (i = 0; data[i]; i++) > + err |= test_hash(sha1, hash, sizeof(hash), > + data[i], strlen(data[i]), > + SHA1); > + > + memset(input, 'a', sizeof(input)); > + for (i = 50; i < sizeof(input); i++) Why 50? > + err |= test_hash(sha1, hash, sizeof(hash), > + input, i, SHA1); > + > + return err; > +} > +#endif > diff --git a/lib/libtpm/sha256.c b/lib/libtpm/sha256.c > index 1a0aa9a..c921ff5 100644 > --- a/lib/libtpm/sha256.c > +++ b/lib/libtpm/sha256.c > @@ -218,3 +218,28 @@ void sha256(const uint8_t *data, uint32_t length, uint8_t *hash) > sha256_do(&ctx, data, length); > memcpy(hash, ctx.h, sizeof(ctx.h)); > } > + > +#ifdef MAIN > + > +#include "sha_test.h" > + > +int main(void) > +{ > + TESTVECTORS(data); > + uint8_t hash[32]; > + char input[64]; > + int err = 0; > + size_t i; > + > + for (i = 0; data[i]; i++) > + err |= test_hash(sha256, hash, sizeof(hash), > + data[i], strlen(data[i]), > + SHA256); > + > + memset(input, 'a', sizeof(input)); > + for (i = 50; i < sizeof(input); i++) Why 50? > + err |= test_hash(sha256, hash, sizeof(hash), input, i, SHA256); > + > + return err; > +} > +#endif > diff --git a/lib/libtpm/sha512.c b/lib/libtpm/sha512.c > index f9267ef..9e856ea 100644 > --- a/lib/libtpm/sha512.c > +++ b/lib/libtpm/sha512.c > @@ -247,3 +247,35 @@ void sha512(const uint8_t *data, uint32_t length, uint8_t *hash) > sha512_do(&ctx, data, length); > memcpy(hash, ctx.h, sizeof(ctx.h)); > } > + > + > +#ifdef MAIN > + > +#include "sha_test.h" > + > +int main(void) > +{ > + TESTVECTORS(data); > + uint8_t hash[64]; > + char input[128]; > + int err = 0; > + size_t i; > + > + for (i = 0; data[i]; i++) { > + err |= test_hash(sha384, hash, 48, Uff. Why 2 separate tests for 48 and sizeof(hash) here but everywhere else it is just sizeof(hash)? > + data[i], strlen(data[i]), > + SHA384); > + err |= test_hash(sha512, hash, sizeof(hash), > + data[i], strlen(data[i]), > + SHA512); > + } > + > + memset(input, 'a', sizeof(input)); > + for (i = 110; i < sizeof(input); i++) { Why 100 and not 50? ;) > + err |= test_hash(sha384, hash, 48, input, i, SHA384); > + err |= test_hash(sha512, hash, sizeof(hash), input, i, SHA512); > + } > + > + return err; > +} > +#endif > diff --git a/lib/libtpm/sha_test.h b/lib/libtpm/sha_test.h > new file mode 100644 > index 0000000..e1358f9 > --- /dev/null > +++ b/lib/libtpm/sha_test.h > @@ -0,0 +1,58 @@ > +/***************************************************************************** > + * Copyright (c) 2021 IBM Corporation > + * All rights reserved. > + * This program and the accompanying materials > + * are made available under the terms of the BSD License > + * which accompanies this distribution, and is available at > + * http://www.opensource.org/licenses/bsd-license.php > + * > + * Contributors: > + * IBM Corporation - initial implementation > + *****************************************************************************/ > + > +#ifndef SHA_TEST_H > +#define SHA_TEST_H > + > +#include <stdio.h> > + > +/* to avoid compilation issues do not include openssl/sha.h */ > +unsigned char *SHA1(const unsigned char *, size_t, unsigned char *); > +unsigned char *SHA256(const unsigned char *, size_t, unsigned char *); > +unsigned char *SHA384(const unsigned char *, size_t, unsigned char *); > +unsigned char *SHA512(const unsigned char *, size_t, unsigned char *); > + > +typedef void (*hashfunc)(const uint8_t *data, uint32_t length, uint8_t *hash); > +typedef unsigned char *(*osslhashfunc)(const unsigned char *, size_t, > + unsigned char *); > + > +#define TESTVECTORS(NAME) \ > +char *NAME[] = { \ > + "", \ > + "abc", \ > + "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", \ > + "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", \ > + NULL \ Use ARRAY_SIZE(NAME) and ditch this last NULL? > +}; > + > +static inline int > +test_hash(hashfunc hf, uint8_t *hash, size_t hashlen, > + const char *data, uint32_t length, > + osslhashfunc osslhf) > +{ > + unsigned char expected[hashlen]; > + int ret = 0; > + > + osslhf((const unsigned char *)data, length, expected); > + > + hf((uint8_t *)data, length, hash); > + if (!memcmp(hash, expected, hashlen)) { > + printf("PASS\n"); > + } else { > + printf("FAIL data: %s\n", data); > + ret = 1; > + } > + > + return ret; > +} > + > +#endif /* SHA_TEST_H */ > diff --git a/lib/libtpm/test.sh b/lib/libtpm/test.sh > new file mode 100755 > index 0000000..f375fbc > --- /dev/null > +++ b/lib/libtpm/test.sh > @@ -0,0 +1,29 @@ > +#!/usr/bin/env bash > +cd $(dirname "$0") > + > +function fail() { > + echo "Test failed" > + exit 1 If we end up here, the produced binaries are not removed. > +} > + > +CC=${HOSTCC:-gcc} > +CFLAGS="-Wall -Wextra -Werror -I../../include -I../../slof -I../../lib/libc/include -DMAIN" > +LDFLAGS="-lcrypto" > + > +echo "SHA-1 test:" > +${CC} ${CFLAGS} sha.c -o sha-test ${LDFLAGS} || exit 1 This produces a little endian binary (as these days PPC64 is pretty much always LE) but SLOF and libtpm are big endian and this is a potential source of bugs, the test must somehow take this into account imho. I am really not sure how to address this though :-/ > +./sha-test || fail > +rm -f sha-test > + > +echo "SHA-256 test:" > +${CC} ${CFLAGS} sha256.c -o sha256-test ${LDFLAGS} || exit 1 > +./sha256-test || fail > +rm -f sha256-test > + > +echo "SHA-384 & 512 test:" > +${CC} ${CFLAGS} sha512.c -o sha512-test ${LDFLAGS} || exit 1 > +./sha512-test || fail > +rm -f sha512-test > + > +echo "All tests passed" > +exit 0 >
On 7/9/21 2:02 AM, Alexey Kardashevskiy wrote: > > > On 09/07/2021 12:53, Stefan Berger wrote: >> From: Stefan Berger <stefanb@linux.ibm.com> >> >> Add test cases for sha1, sha256, sha384, and sha512 and a test script >> to run the test cases. >> >> Signed-off-by: Stefan Berger <stefanb@linux.ibm.com> >> --- >> lib/libtpm/sha.c | 26 +++++++++++++++++++ >> lib/libtpm/sha256.c | 25 +++++++++++++++++++ >> lib/libtpm/sha512.c | 32 ++++++++++++++++++++++++ >> lib/libtpm/sha_test.h | 58 +++++++++++++++++++++++++++++++++++++++++++ >> lib/libtpm/test.sh | 29 ++++++++++++++++++++++ >> 5 files changed, 170 insertions(+) >> create mode 100644 lib/libtpm/sha_test.h >> create mode 100755 lib/libtpm/test.sh >> >> diff --git a/lib/libtpm/sha.c b/lib/libtpm/sha.c >> index 43de658..6e8b19b 100644 >> --- a/lib/libtpm/sha.c >> +++ b/lib/libtpm/sha.c >> @@ -203,3 +203,29 @@ void sha1(const uint8_t *data, uint32_t length, >> uint8_t *hash) >> sha1_do(&ctx, data, length); >> memcpy(hash, &ctx.h[0], 20); >> } >> + >> +#ifdef MAIN >> + >> +#include "sha_test.h" >> + >> +int main(void) >> +{ >> + TESTVECTORS(data); >> + uint8_t hash[20]; >> + char input[64]; >> + int err = 0; >> + size_t i; >> + >> + for (i = 0; data[i]; i++) >> + err |= test_hash(sha1, hash, sizeof(hash), >> + data[i], strlen(data[i]), >> + SHA1); >> + >> + memset(input, 'a', sizeof(input)); >> + for (i = 50; i < sizeof(input); i++) > > > Why 50? There's a critical point in the input size for sha1 at around 56 bytes. I mainly wanted to cover that. https://github.com/aik/SLOF/blob/master/lib/libtpm/sha.c#L170 The same is true for sha256 at 56 bytes: https://github.com/aik/SLOF/blob/master/lib/libtpm/sha256.c#L176 For sha512/sha384 it is at 112 bytes: https://github.com/aik/SLOF/blob/master/lib/libtpm/sha512.c#L186 > > >> + err |= test_hash(sha256, hash, sizeof(hash), input, i, SHA256); >> + >> + return err; >> +} >> +#endif >> diff --git a/lib/libtpm/sha512.c b/lib/libtpm/sha512.c >> index f9267ef..9e856ea 100644 >> --- a/lib/libtpm/sha512.c >> +++ b/lib/libtpm/sha512.c >> @@ -247,3 +247,35 @@ void sha512(const uint8_t *data, uint32_t >> length, uint8_t *hash) >> sha512_do(&ctx, data, length); >> memcpy(hash, ctx.h, sizeof(ctx.h)); >> } >> + >> + >> +#ifdef MAIN >> + >> +#include "sha_test.h" >> + >> +int main(void) >> +{ >> + TESTVECTORS(data); >> + uint8_t hash[64]; >> + char input[128]; >> + int err = 0; >> + size_t i; >> + >> + for (i = 0; data[i]; i++) { >> + err |= test_hash(sha384, hash, 48, > > Uff. Why 2 separate tests for 48 and sizeof(hash) here but everywhere > else it is just sizeof(hash)? Ok, let me revise. > > > >> + data[i], strlen(data[i]), >> + SHA384); >> + err |= test_hash(sha512, hash, sizeof(hash), >> + data[i], strlen(data[i]), >> + SHA512); >> + } >> + >> + memset(input, 'a', sizeof(input)); >> + for (i = 110; i < sizeof(input); i++) { > > > Why 100 and not 50? ;) See above. > > >> + err |= test_hash(sha384, hash, 48, input, i, SHA384); >> + err |= test_hash(sha512, hash, sizeof(hash), input, i, SHA512); >> + } >> + >> + return err; >> +} >> +#endif >> diff --git a/lib/libtpm/sha_test.h b/lib/libtpm/sha_test.h >> new file mode 100644 >> index 0000000..e1358f9 >> --- /dev/null >> +++ b/lib/libtpm/sha_test.h >> @@ -0,0 +1,58 @@ >> +/***************************************************************************** >> >> + * Copyright (c) 2021 IBM Corporation >> + * All rights reserved. >> + * This program and the accompanying materials >> + * are made available under the terms of the BSD License >> + * which accompanies this distribution, and is available at >> + * http://www.opensource.org/licenses/bsd-license.php >> + * >> + * Contributors: >> + * IBM Corporation - initial implementation >> + >> *****************************************************************************/ >> + >> +#ifndef SHA_TEST_H >> +#define SHA_TEST_H >> + >> +#include <stdio.h> >> + >> +/* to avoid compilation issues do not include openssl/sha.h */ >> +unsigned char *SHA1(const unsigned char *, size_t, unsigned char *); >> +unsigned char *SHA256(const unsigned char *, size_t, unsigned char *); >> +unsigned char *SHA384(const unsigned char *, size_t, unsigned char *); >> +unsigned char *SHA512(const unsigned char *, size_t, unsigned char *); >> + >> +typedef void (*hashfunc)(const uint8_t *data, uint32_t length, >> uint8_t *hash); >> +typedef unsigned char *(*osslhashfunc)(const unsigned char *, size_t, >> + unsigned char *); >> + >> +#define TESTVECTORS(NAME) \ >> +char *NAME[] = { \ >> + "", \ >> + "abc", \ >> + "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", \ >> + >> "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", >> \ >> + NULL \ > > > Use ARRAY_SIZE(NAME) and ditch this last NULL? Ok. > > >> +}; >> + >> +static inline int >> +test_hash(hashfunc hf, uint8_t *hash, size_t hashlen, >> + const char *data, uint32_t length, >> + osslhashfunc osslhf) >> +{ >> + unsigned char expected[hashlen]; >> + int ret = 0; >> + >> + osslhf((const unsigned char *)data, length, expected); >> + >> + hf((uint8_t *)data, length, hash); >> + if (!memcmp(hash, expected, hashlen)) { >> + printf("PASS\n"); >> + } else { >> + printf("FAIL data: %s\n", data); >> + ret = 1; >> + } >> + >> + return ret; >> +} >> + >> +#endif /* SHA_TEST_H */ >> diff --git a/lib/libtpm/test.sh b/lib/libtpm/test.sh >> new file mode 100755 >> index 0000000..f375fbc >> --- /dev/null >> +++ b/lib/libtpm/test.sh >> @@ -0,0 +1,29 @@ >> +#!/usr/bin/env bash >> +cd $(dirname "$0") >> + >> +function fail() { >> + echo "Test failed" >> + exit 1 > > If we end up here, the produced binaries are not removed. > > >> +} >> + >> +CC=${HOSTCC:-gcc} >> +CFLAGS="-Wall -Wextra -Werror -I../../include -I../../slof >> -I../../lib/libc/include -DMAIN" >> +LDFLAGS="-lcrypto" >> + >> +echo "SHA-1 test:" >> +${CC} ${CFLAGS} sha.c -o sha-test ${LDFLAGS} || exit 1 > > > This produces a little endian binary (as these days PPC64 is pretty > much always LE) but SLOF and libtpm are big endian and this is a > potential source of bugs, the test must somehow take this into account > imho. I am really not sure how to address this though :-/ I ran it on an old big endian Fedora 28. Well, it works there. The only other choice would be to add this as self-tests into SLOF and use hard-coded results for comparison. > > > >> +./sha-test || fail >> +rm -f sha-test >> + >> +echo "SHA-256 test:" >> +${CC} ${CFLAGS} sha256.c -o sha256-test ${LDFLAGS} || exit 1 >> +./sha256-test || fail >> +rm -f sha256-test >> + >> +echo "SHA-384 & 512 test:" >> +${CC} ${CFLAGS} sha512.c -o sha512-test ${LDFLAGS} || exit 1 >> +./sha512-test || fail >> +rm -f sha512-test >> + >> +echo "All tests passed" >> +exit 0 >> >
On 09/07/2021 22:07, Stefan Berger wrote: > On 7/9/21 2:02 AM, Alexey Kardashevskiy wrote: > >> >> >> On 09/07/2021 12:53, Stefan Berger wrote: >>> From: Stefan Berger <stefanb@linux.ibm.com> >>> >>> Add test cases for sha1, sha256, sha384, and sha512 and a test script >>> to run the test cases. >>> >>> Signed-off-by: Stefan Berger <stefanb@linux.ibm.com> >>> --- >>> lib/libtpm/sha.c | 26 +++++++++++++++++++ >>> lib/libtpm/sha256.c | 25 +++++++++++++++++++ >>> lib/libtpm/sha512.c | 32 ++++++++++++++++++++++++ >>> lib/libtpm/sha_test.h | 58 +++++++++++++++++++++++++++++++++++++++++++ >>> lib/libtpm/test.sh | 29 ++++++++++++++++++++++ >>> 5 files changed, 170 insertions(+) >>> create mode 100644 lib/libtpm/sha_test.h >>> create mode 100755 lib/libtpm/test.sh >>> >>> diff --git a/lib/libtpm/sha.c b/lib/libtpm/sha.c >>> index 43de658..6e8b19b 100644 >>> --- a/lib/libtpm/sha.c >>> +++ b/lib/libtpm/sha.c >>> @@ -203,3 +203,29 @@ void sha1(const uint8_t *data, uint32_t length, >>> uint8_t *hash) >>> sha1_do(&ctx, data, length); >>> memcpy(hash, &ctx.h[0], 20); >>> } >>> + >>> +#ifdef MAIN >>> + >>> +#include "sha_test.h" >>> + >>> +int main(void) >>> +{ >>> + TESTVECTORS(data); >>> + uint8_t hash[20]; >>> + char input[64]; >>> + int err = 0; >>> + size_t i; >>> + >>> + for (i = 0; data[i]; i++) >>> + err |= test_hash(sha1, hash, sizeof(hash), >>> + data[i], strlen(data[i]), >>> + SHA1); >>> + >>> + memset(input, 'a', sizeof(input)); >>> + for (i = 50; i < sizeof(input); i++) >> >> >> Why 50? > > > There's a critical point in the input size for sha1 at around 56 bytes. > I mainly wanted to cover that. This is fine but then it calls for a macro, something like SHA1_CRIT_SIZE which you then use in sha.c and in the test. I never ever wrote a single bit of sha so I really wish to have some clues here. > https://github.com/aik/SLOF/blob/master/lib/libtpm/sha.c#L170 > > The same is true for sha256 at 56 bytes: > > https://github.com/aik/SLOF/blob/master/lib/libtpm/sha256.c#L176 > > For sha512/sha384 it is at 112 bytes: > > https://github.com/aik/SLOF/blob/master/lib/libtpm/sha512.c#L186 > > >> >> >>> + err |= test_hash(sha256, hash, sizeof(hash), input, i, SHA256); >>> + >>> + return err; >>> +} >>> +#endif >>> diff --git a/lib/libtpm/sha512.c b/lib/libtpm/sha512.c >>> index f9267ef..9e856ea 100644 >>> --- a/lib/libtpm/sha512.c >>> +++ b/lib/libtpm/sha512.c >>> @@ -247,3 +247,35 @@ void sha512(const uint8_t *data, uint32_t >>> length, uint8_t *hash) >>> sha512_do(&ctx, data, length); >>> memcpy(hash, ctx.h, sizeof(ctx.h)); >>> } >>> + >>> + >>> +#ifdef MAIN >>> + >>> +#include "sha_test.h" >>> + >>> +int main(void) >>> +{ >>> + TESTVECTORS(data); >>> + uint8_t hash[64]; >>> + char input[128]; >>> + int err = 0; >>> + size_t i; >>> + >>> + for (i = 0; data[i]; i++) { >>> + err |= test_hash(sha384, hash, 48, >> >> Uff. Why 2 separate tests for 48 and sizeof(hash) here but everywhere >> else it is just sizeof(hash)? > > Ok, let me revise. > > >> >> >> >>> + data[i], strlen(data[i]), >>> + SHA384); >>> + err |= test_hash(sha512, hash, sizeof(hash), >>> + data[i], strlen(data[i]), >>> + SHA512); >>> + } >>> + >>> + memset(input, 'a', sizeof(input)); >>> + for (i = 110; i < sizeof(input); i++) { >> >> >> Why 100 and not 50? ;) > > > See above. > >> >> >>> + err |= test_hash(sha384, hash, 48, input, i, SHA384); >>> + err |= test_hash(sha512, hash, sizeof(hash), input, i, SHA512); >>> + } >>> + >>> + return err; >>> +} >>> +#endif >>> diff --git a/lib/libtpm/sha_test.h b/lib/libtpm/sha_test.h >>> new file mode 100644 >>> index 0000000..e1358f9 >>> --- /dev/null >>> +++ b/lib/libtpm/sha_test.h >>> @@ -0,0 +1,58 @@ >>> +/***************************************************************************** >>> >>> + * Copyright (c) 2021 IBM Corporation >>> + * All rights reserved. >>> + * This program and the accompanying materials >>> + * are made available under the terms of the BSD License >>> + * which accompanies this distribution, and is available at >>> + * http://www.opensource.org/licenses/bsd-license.php >>> + * >>> + * Contributors: >>> + * IBM Corporation - initial implementation >>> + >>> *****************************************************************************/ >>> >>> + >>> +#ifndef SHA_TEST_H >>> +#define SHA_TEST_H >>> + >>> +#include <stdio.h> >>> + >>> +/* to avoid compilation issues do not include openssl/sha.h */ >>> +unsigned char *SHA1(const unsigned char *, size_t, unsigned char *); >>> +unsigned char *SHA256(const unsigned char *, size_t, unsigned char *); >>> +unsigned char *SHA384(const unsigned char *, size_t, unsigned char *); >>> +unsigned char *SHA512(const unsigned char *, size_t, unsigned char *); >>> + >>> +typedef void (*hashfunc)(const uint8_t *data, uint32_t length, >>> uint8_t *hash); >>> +typedef unsigned char *(*osslhashfunc)(const unsigned char *, size_t, >>> + unsigned char *); >>> + >>> +#define TESTVECTORS(NAME) \ >>> +char *NAME[] = { \ >>> + "", \ >>> + "abc", \ >>> + "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", \ >>> + >>> "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", >>> \ >>> + NULL \ >> >> >> Use ARRAY_SIZE(NAME) and ditch this last NULL? > > > Ok. > > >> >> >>> +}; >>> + >>> +static inline int >>> +test_hash(hashfunc hf, uint8_t *hash, size_t hashlen, >>> + const char *data, uint32_t length, >>> + osslhashfunc osslhf) >>> +{ >>> + unsigned char expected[hashlen]; >>> + int ret = 0; >>> + >>> + osslhf((const unsigned char *)data, length, expected); >>> + >>> + hf((uint8_t *)data, length, hash); >>> + if (!memcmp(hash, expected, hashlen)) { >>> + printf("PASS\n"); >>> + } else { >>> + printf("FAIL data: %s\n", data); >>> + ret = 1; >>> + } >>> + >>> + return ret; >>> +} >>> + >>> +#endif /* SHA_TEST_H */ >>> diff --git a/lib/libtpm/test.sh b/lib/libtpm/test.sh >>> new file mode 100755 >>> index 0000000..f375fbc >>> --- /dev/null >>> +++ b/lib/libtpm/test.sh >>> @@ -0,0 +1,29 @@ >>> +#!/usr/bin/env bash >>> +cd $(dirname "$0") >>> + >>> +function fail() { >>> + echo "Test failed" >>> + exit 1 >> >> If we end up here, the produced binaries are not removed. >> >> >>> +} >>> + >>> +CC=${HOSTCC:-gcc} >>> +CFLAGS="-Wall -Wextra -Werror -I../../include -I../../slof >>> -I../../lib/libc/include -DMAIN" >>> +LDFLAGS="-lcrypto" >>> + >>> +echo "SHA-1 test:" >>> +${CC} ${CFLAGS} sha.c -o sha-test ${LDFLAGS} || exit 1 >> >> >> This produces a little endian binary (as these days PPC64 is pretty >> much always LE) but SLOF and libtpm are big endian and this is a >> potential source of bugs, the test must somehow take this into account >> imho. I am really not sure how to address this though :-/ > > > I ran it on an old big endian Fedora 28. Well, it works there. ok, this will do, may be leave a note in the commit log. Thanks, > The only > other choice would be to add this as self-tests into SLOF and use > hard-coded results for comparison. > > >> >> >> >>> +./sha-test || fail >>> +rm -f sha-test >>> + >>> +echo "SHA-256 test:" >>> +${CC} ${CFLAGS} sha256.c -o sha256-test ${LDFLAGS} || exit 1 >>> +./sha256-test || fail >>> +rm -f sha256-test >>> + >>> +echo "SHA-384 & 512 test:" >>> +${CC} ${CFLAGS} sha512.c -o sha512-test ${LDFLAGS} || exit 1 >>> +./sha512-test || fail >>> +rm -f sha512-test >>> + >>> +echo "All tests passed" >>> +exit 0 >>> >>
On 7/9/21 10:07 AM, Alexey Kardashevskiy wrote: > > > On 09/07/2021 22:07, Stefan Berger wrote: >> On 7/9/21 2:02 AM, Alexey Kardashevskiy wrote: >> >>> >>> >>> On 09/07/2021 12:53, Stefan Berger wrote: >>>> From: Stefan Berger <stefanb@linux.ibm.com> >>>> >>>> Add test cases for sha1, sha256, sha384, and sha512 and a test script >>>> to run the test cases. >>>> >>>> Signed-off-by: Stefan Berger <stefanb@linux.ibm.com> >>>> --- >>>> lib/libtpm/sha.c | 26 +++++++++++++++++++ >>>> lib/libtpm/sha256.c | 25 +++++++++++++++++++ >>>> lib/libtpm/sha512.c | 32 ++++++++++++++++++++++++ >>>> lib/libtpm/sha_test.h | 58 >>>> +++++++++++++++++++++++++++++++++++++++++++ >>>> lib/libtpm/test.sh | 29 ++++++++++++++++++++++ >>>> 5 files changed, 170 insertions(+) >>>> create mode 100644 lib/libtpm/sha_test.h >>>> create mode 100755 lib/libtpm/test.sh >>>> >>>> diff --git a/lib/libtpm/sha.c b/lib/libtpm/sha.c >>>> index 43de658..6e8b19b 100644 >>>> --- a/lib/libtpm/sha.c >>>> +++ b/lib/libtpm/sha.c >>>> @@ -203,3 +203,29 @@ void sha1(const uint8_t *data, uint32_t >>>> length, uint8_t *hash) >>>> sha1_do(&ctx, data, length); >>>> memcpy(hash, &ctx.h[0], 20); >>>> } >>>> + >>>> +#ifdef MAIN >>>> + >>>> +#include "sha_test.h" >>>> + >>>> +int main(void) >>>> +{ >>>> + TESTVECTORS(data); >>>> + uint8_t hash[20]; >>>> + char input[64]; >>>> + int err = 0; >>>> + size_t i; >>>> + >>>> + for (i = 0; data[i]; i++) >>>> + err |= test_hash(sha1, hash, sizeof(hash), >>>> + data[i], strlen(data[i]), >>>> + SHA1); >>>> + >>>> + memset(input, 'a', sizeof(input)); >>>> + for (i = 50; i < sizeof(input); i++) >>> >>> >>> Why 50? >> >> >> There's a critical point in the input size for sha1 at around 56 >> bytes. I mainly wanted to cover that. > > This is fine but then it calls for a macro, something like > SHA1_CRIT_SIZE which you then use in sha.c and in the test. I never > ever wrote a single bit of sha so I really wish to have some clues here. I now wrote a comment into the code explaining what the critical input size is and that we want to cover that along with some more tests around that size...
diff --git a/lib/libtpm/sha.c b/lib/libtpm/sha.c index 43de658..6e8b19b 100644 --- a/lib/libtpm/sha.c +++ b/lib/libtpm/sha.c @@ -203,3 +203,29 @@ void sha1(const uint8_t *data, uint32_t length, uint8_t *hash) sha1_do(&ctx, data, length); memcpy(hash, &ctx.h[0], 20); } + +#ifdef MAIN + +#include "sha_test.h" + +int main(void) +{ + TESTVECTORS(data); + uint8_t hash[20]; + char input[64]; + int err = 0; + size_t i; + + for (i = 0; data[i]; i++) + err |= test_hash(sha1, hash, sizeof(hash), + data[i], strlen(data[i]), + SHA1); + + memset(input, 'a', sizeof(input)); + for (i = 50; i < sizeof(input); i++) + err |= test_hash(sha1, hash, sizeof(hash), + input, i, SHA1); + + return err; +} +#endif diff --git a/lib/libtpm/sha256.c b/lib/libtpm/sha256.c index 1a0aa9a..c921ff5 100644 --- a/lib/libtpm/sha256.c +++ b/lib/libtpm/sha256.c @@ -218,3 +218,28 @@ void sha256(const uint8_t *data, uint32_t length, uint8_t *hash) sha256_do(&ctx, data, length); memcpy(hash, ctx.h, sizeof(ctx.h)); } + +#ifdef MAIN + +#include "sha_test.h" + +int main(void) +{ + TESTVECTORS(data); + uint8_t hash[32]; + char input[64]; + int err = 0; + size_t i; + + for (i = 0; data[i]; i++) + err |= test_hash(sha256, hash, sizeof(hash), + data[i], strlen(data[i]), + SHA256); + + memset(input, 'a', sizeof(input)); + for (i = 50; i < sizeof(input); i++) + err |= test_hash(sha256, hash, sizeof(hash), input, i, SHA256); + + return err; +} +#endif diff --git a/lib/libtpm/sha512.c b/lib/libtpm/sha512.c index f9267ef..9e856ea 100644 --- a/lib/libtpm/sha512.c +++ b/lib/libtpm/sha512.c @@ -247,3 +247,35 @@ void sha512(const uint8_t *data, uint32_t length, uint8_t *hash) sha512_do(&ctx, data, length); memcpy(hash, ctx.h, sizeof(ctx.h)); } + + +#ifdef MAIN + +#include "sha_test.h" + +int main(void) +{ + TESTVECTORS(data); + uint8_t hash[64]; + char input[128]; + int err = 0; + size_t i; + + for (i = 0; data[i]; i++) { + err |= test_hash(sha384, hash, 48, + data[i], strlen(data[i]), + SHA384); + err |= test_hash(sha512, hash, sizeof(hash), + data[i], strlen(data[i]), + SHA512); + } + + memset(input, 'a', sizeof(input)); + for (i = 110; i < sizeof(input); i++) { + err |= test_hash(sha384, hash, 48, input, i, SHA384); + err |= test_hash(sha512, hash, sizeof(hash), input, i, SHA512); + } + + return err; +} +#endif diff --git a/lib/libtpm/sha_test.h b/lib/libtpm/sha_test.h new file mode 100644 index 0000000..e1358f9 --- /dev/null +++ b/lib/libtpm/sha_test.h @@ -0,0 +1,58 @@ +/***************************************************************************** + * Copyright (c) 2021 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + +#ifndef SHA_TEST_H +#define SHA_TEST_H + +#include <stdio.h> + +/* to avoid compilation issues do not include openssl/sha.h */ +unsigned char *SHA1(const unsigned char *, size_t, unsigned char *); +unsigned char *SHA256(const unsigned char *, size_t, unsigned char *); +unsigned char *SHA384(const unsigned char *, size_t, unsigned char *); +unsigned char *SHA512(const unsigned char *, size_t, unsigned char *); + +typedef void (*hashfunc)(const uint8_t *data, uint32_t length, uint8_t *hash); +typedef unsigned char *(*osslhashfunc)(const unsigned char *, size_t, + unsigned char *); + +#define TESTVECTORS(NAME) \ +char *NAME[] = { \ + "", \ + "abc", \ + "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", \ + "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", \ + NULL \ +}; + +static inline int +test_hash(hashfunc hf, uint8_t *hash, size_t hashlen, + const char *data, uint32_t length, + osslhashfunc osslhf) +{ + unsigned char expected[hashlen]; + int ret = 0; + + osslhf((const unsigned char *)data, length, expected); + + hf((uint8_t *)data, length, hash); + if (!memcmp(hash, expected, hashlen)) { + printf("PASS\n"); + } else { + printf("FAIL data: %s\n", data); + ret = 1; + } + + return ret; +} + +#endif /* SHA_TEST_H */ diff --git a/lib/libtpm/test.sh b/lib/libtpm/test.sh new file mode 100755 index 0000000..f375fbc --- /dev/null +++ b/lib/libtpm/test.sh @@ -0,0 +1,29 @@ +#!/usr/bin/env bash +cd $(dirname "$0") + +function fail() { + echo "Test failed" + exit 1 +} + +CC=${HOSTCC:-gcc} +CFLAGS="-Wall -Wextra -Werror -I../../include -I../../slof -I../../lib/libc/include -DMAIN" +LDFLAGS="-lcrypto" + +echo "SHA-1 test:" +${CC} ${CFLAGS} sha.c -o sha-test ${LDFLAGS} || exit 1 +./sha-test || fail +rm -f sha-test + +echo "SHA-256 test:" +${CC} ${CFLAGS} sha256.c -o sha256-test ${LDFLAGS} || exit 1 +./sha256-test || fail +rm -f sha256-test + +echo "SHA-384 & 512 test:" +${CC} ${CFLAGS} sha512.c -o sha512-test ${LDFLAGS} || exit 1 +./sha512-test || fail +rm -f sha512-test + +echo "All tests passed" +exit 0