[SLOF] [PATCH v3 6/7] tcgbios: Add test cases and test script to run them

Stefan Berger stefanb at linux.ibm.com
Fri Jul 9 22:07:50 AEST 2021


On 7/9/21 2:02 AM, Alexey Kardashevskiy wrote:

>
>
> On 09/07/2021 12:53, Stefan Berger wrote:
>> From: Stefan Berger <stefanb at 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 at 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
>>
>


More information about the SLOF mailing list