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

Alexey Kardashevskiy aik at ozlabs.ru
Sat Jul 10 00:07:18 AEST 2021



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 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.

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
>>>
>>

-- 
Alexey


More information about the SLOF mailing list