From: Loup Vaillant Date: Sun, 24 Nov 2019 13:09:41 +0000 (+0100) Subject: Put common test utilities in its own module X-Git-Url: https://git.codecow.com/?a=commitdiff_plain;h=79ce972785c32d8a43b7da1ef617c42ad266171c;p=Monocypher.git Put common test utilities in its own module This will help making separate test suite. --- diff --git a/makefile b/makefile index 2392420..a15842a 100644 --- a/makefile +++ b/makefile @@ -106,6 +106,7 @@ lib/monocypher.o lib/sha512.o: # Test & speed libraries TEST_COMMON = tests/utils.h src/monocypher.h src/optional/sha512.h SPEED = tests/speed +lib/utils.o :tests/utils.c lib/test.o :tests/test.c $(TEST_COMMON) tests/vectors.h lib/speed.o :$(SPEED)/speed.c $(TEST_COMMON) $(SPEED)/speed.h lib/speed-tweetnacl.o:$(SPEED)/speed-tweetnacl.c $(TEST_COMMON) $(SPEED)/speed.h @@ -153,22 +154,22 @@ lib/speed-c25519.o:$(SPEED)/speed-c25519.c \ # test & speed executables -test.out : lib/test.o lib/monocypher.o lib/sha512.o -speed.out: lib/speed.o lib/monocypher.o lib/sha512.o +test.out : lib/test.o lib/utils.o lib/monocypher.o lib/sha512.o +speed.out: lib/speed.o lib/utils.o lib/monocypher.o lib/sha512.o test.out speed.out: $(CC) $(CFLAGS) -I src -I src/optional -o $@ $^ -speed-sodium.out: lib/speed-sodium.o +speed-sodium.out: lib/speed-sodium.o lib/utils.o $(CC) $(CFLAGS) -o $@ $^ \ `pkg-config --cflags libsodium` \ `pkg-config --libs libsodium` -speed-hydrogen.out: lib/speed-hydrogen.o +speed-hydrogen.out: lib/speed-hydrogen.o lib/utils.o $(CC) $(CFLAGS) -o $@ $^ \ `pkg-config --cflags libhydrogen` \ `pkg-config --libs libhydrogen` lib/tweetnacl.o: tests/externals/tweetnacl.c tests/externals/tweetnacl.h $(CC) $(CFLAGS) -c -o $@ $< -speed-tweetnacl.out: lib/speed-tweetnacl.o lib/tweetnacl.o -speed-c25519.out : lib/speed-c25519.o $(C25519_OBJECTS) +speed-tweetnacl.out: lib/speed-tweetnacl.o lib/tweetnacl.o lib/utils.o +speed-c25519.out : lib/speed-c25519.o $(C25519_OBJECTS) lib/utils.o speed-tweetnacl.out speed-c25519.out: $(CC) $(CFLAGS) -o $@ $^ diff --git a/tests/gen/makefile b/tests/gen/makefile index 85f0f32..d0bbd7d 100644 --- a/tests/gen/makefile +++ b/tests/gen/makefile @@ -21,6 +21,9 @@ clean: %.vec: %.out ./$< > $@ +utils.o: ../utils.c ../utils.h + $(CC) $(CFLAGS) -c $< -o $@ + %.o: %.c ../utils.h ../externals/ed25519-donna/ed25519.h $(CC) $(CFLAGS) -c $< \ -I .. \ @@ -29,7 +32,7 @@ clean: -I ../../src/optional \ $$(pkg-config --cflags libsodium) -%.out: %.o ed25519.o +%.out: %.o ed25519.o utils.o $(CC) $(CFLAGS) -o $@ $^ \ $$(pkg-config --libs libsodium) diff --git a/tests/test.c b/tests/test.c index c195e46..f2a6013 100644 --- a/tests/test.c +++ b/tests/test.c @@ -1,7 +1,6 @@ #include #include #include -#include #include "monocypher.h" #include "sha512.h" #include "utils.h" @@ -13,83 +12,9 @@ #define BLAKE2B_BLOCK_SIZE 128 #define SHA_512_BLOCK_SIZE 128 -///////////////// -/// Utilities /// -///////////////// - -static void* alloc(size_t size) -{ - if (size == 0) { - // Some systems refuse to allocate zero bytes. - // So we don't. Instead, we just return a non-sensical pointer. - // It shouldn't be dereferenced anyway. - return NULL; - } - void *buf = malloc(size); - if (buf == NULL) { - fprintf(stderr, "Allocation failed: 0x%zx bytes\n", size); - exit(1); - } - return buf; -} - -typedef struct { - u8 *buf; - size_t size; -} vector; - -int zerocmp(const u8 *p, size_t n) -{ - FOR (i, 0, n) { - if (p[i] != 0) { return -1; } - } - return 0; -} - -static int test(void (*f)(const vector[], vector*), - const char *name, size_t nb_inputs, - size_t nb_vectors, u8 **vectors, size_t *sizes) -{ - int status = 0; - int nb_tests = 0; - size_t idx = 0; - vector *in; - in = (vector*)alloc(nb_vectors * sizeof(vector)); - while (idx < nb_vectors) { - size_t out_size = sizes[idx + nb_inputs]; - vector out; - out.buf = (u8*)alloc(out_size); - out.size = out_size; - FOR (i, 0, nb_inputs) { - in[i].buf = vectors[idx+i]; - in[i].size = sizes [idx+i]; - } - f(in, &out); - vector expected; - expected.buf = vectors[idx+nb_inputs]; - expected.size = sizes [idx+nb_inputs]; - status |= out.size - expected.size; - if (out.size != 0) { - status |= memcmp(out.buf, expected.buf, out.size); - } - free(out.buf); - idx += nb_inputs + 1; - nb_tests++; - } - free(in); - printf("%s %4d tests: %s\n", - status != 0 ? "FAILED" : "OK", nb_tests, name); - return status; -} - -#define TEST(name, nb_inputs) test(name, #name, nb_inputs, \ - nb_##name##_vectors, \ - name##_vectors, \ - name##_sizes) - -//////////////////////// -/// The tests proper /// -//////////////////////// +//////////////////////////// +/// Tests aginst vectors /// +//////////////////////////// static void chacha20(const vector in[], vector *out) { const vector *key = in; @@ -271,7 +196,6 @@ static int test_x25519() ////////////////////////////// /// Self consistency tests /// ////////////////////////////// - static int p_verify(size_t size, int (*compare)(const u8*, const u8*)) { int status = 0; @@ -854,6 +778,11 @@ static int p_auth() return status; } +#define TEST(name, nb_inputs) vector_test(name, #name, nb_inputs, \ + nb_##name##_vectors, \ + name##_vectors, \ + name##_sizes) + int main(int argc, char *argv[]) { if (argc > 1) { diff --git a/tests/utils.c b/tests/utils.c new file mode 100644 index 0000000..f3d367b --- /dev/null +++ b/tests/utils.c @@ -0,0 +1,127 @@ +#include "utils.h" + +#include +#include +#include + +void store64_le(u8 out[8], u64 in) +{ + out[0] = in & 0xff; + out[1] = (in >> 8) & 0xff; + out[2] = (in >> 16) & 0xff; + out[3] = (in >> 24) & 0xff; + out[4] = (in >> 32) & 0xff; + out[5] = (in >> 40) & 0xff; + out[6] = (in >> 48) & 0xff; + out[7] = (in >> 56) & 0xff; +} + +u64 load64_le(const u8 s[8]) +{ + return (u64)s[0] + | ((u64)s[1] << 8) + | ((u64)s[2] << 16) + | ((u64)s[3] << 24) + | ((u64)s[4] << 32) + | ((u64)s[5] << 40) + | ((u64)s[6] << 48) + | ((u64)s[7] << 56); +} + +// Must be seeded with a nonzero value. +// Accessible from the outside so we can modify it +u64 random_state = 12345; + +// Pseudo-random 64 bit number, based on xorshift* +u64 rand64() +{ + random_state ^= random_state >> 12; + random_state ^= random_state << 25; + random_state ^= random_state >> 27; + return random_state * 0x2545F4914F6CDD1D; // magic constant +} + +void p_random(u8 *stream, size_t size) +{ + FOR (i, 0, size) { + stream[i] = (u8)rand64(); + } +} + +void print_vector(const u8 *buf, size_t size) +{ + FOR (i, 0, size) { + printf("%x%x", buf[i] >> 4, buf[i] & 0x0f); + } + printf(":\n"); +} + +void print_number(u64 n) +{ + u8 buf[8]; + store64_le(buf, n); + print_vector(buf, 8); +} + + + +void* alloc(size_t size) +{ + if (size == 0) { + // Some systems refuse to allocate zero bytes. + // So we don't. Instead, we just return a non-sensical pointer. + // It shouldn't be dereferenced anyway. + return NULL; + } + void *buf = malloc(size); + if (buf == NULL) { + fprintf(stderr, "Allocation failed: 0x%zx bytes\n", size); + exit(1); + } + return buf; +} + +int zerocmp(const u8 *p, size_t n) +{ + FOR (i, 0, n) { + if (p[i] != 0) { return -1; } + } + return 0; +} + +int vector_test(void (*f)(const vector[], vector*), + const char *name, size_t nb_inputs, + size_t nb_vectors, u8 **vectors, size_t *sizes) +{ + int status = 0; + int nb_tests = 0; + size_t idx = 0; + vector *in; + in = (vector*)alloc(nb_vectors * sizeof(vector)); + while (idx < nb_vectors) { + size_t out_size = sizes[idx + nb_inputs]; + vector out; + out.buf = (u8*)alloc(out_size); + out.size = out_size; + FOR (i, 0, nb_inputs) { + in[i].buf = vectors[idx+i]; + in[i].size = sizes [idx+i]; + } + f(in, &out); + vector expected; + expected.buf = vectors[idx+nb_inputs]; + expected.size = sizes [idx+nb_inputs]; + status |= out.size - expected.size; + if (out.size != 0) { + status |= memcmp(out.buf, expected.buf, out.size); + } + free(out.buf); + idx += nb_inputs + 1; + nb_tests++; + } + free(in); + printf("%s %4d tests: %s\n", + status != 0 ? "FAILED" : "OK", nb_tests, name); + return status; +} + diff --git a/tests/utils.h b/tests/utils.h index 9d7bcc1..fd77abd 100644 --- a/tests/utils.h +++ b/tests/utils.h @@ -3,7 +3,6 @@ #include #include -#include typedef int8_t i8; typedef uint8_t u8; @@ -22,63 +21,25 @@ typedef uint64_t u64; } while (0) #define RANDOM_INPUT(name, size) u8 name[size]; p_random(name, size) -static void store64_le(u8 out[8], u64 in) -{ - out[0] = in & 0xff; - out[1] = (in >> 8) & 0xff; - out[2] = (in >> 16) & 0xff; - out[3] = (in >> 24) & 0xff; - out[4] = (in >> 32) & 0xff; - out[5] = (in >> 40) & 0xff; - out[6] = (in >> 48) & 0xff; - out[7] = (in >> 56) & 0xff; -} +extern u64 random_state; // state of the RNG -u64 load64_le(const u8 s[8]) -{ - return (u64)s[0] - | ((u64)s[1] << 8) - | ((u64)s[2] << 16) - | ((u64)s[3] << 24) - | ((u64)s[4] << 32) - | ((u64)s[5] << 40) - | ((u64)s[6] << 48) - | ((u64)s[7] << 56); -} +typedef struct { + u8 *buf; + size_t size; +} vector; -// Must be seeded with a nonzero value. -// Accessible from the outside so we can modify it -static u64 random_state = 12345; +void store64_le(u8 out[8], u64 in); +u64 load64_le(const u8 s[8]); +u64 rand64(); // Pseudo-random 64 bit number, based on xorshift* +void p_random(u8 *stream, size_t size); +void print_vector(const u8 *buf, size_t size); +void print_number(u64 n); +void* alloc(size_t size); -// Pseudo-random 64 bit number, based on xorshift* -u64 rand64() -{ - random_state ^= random_state >> 12; - random_state ^= random_state << 25; - random_state ^= random_state >> 27; - return random_state * 0x2545F4914F6CDD1D; // magic constant -} +int zerocmp(const u8 *p, size_t n); -void p_random(u8 *stream, size_t size) -{ - FOR (i, 0, size) { - stream[i] = (u8)rand64(); - } -} - -void print_vector(const u8 *buf, size_t size) -{ - FOR (i, 0, size) { - printf("%x%x", buf[i] >> 4, buf[i] & 0x0f); - } - printf(":\n"); -} - -void print_number(u64 n) -{ - u8 buf[8]; - store64_le(buf, n); - print_vector(buf, 8); -} +int vector_test(void (*f)(const vector[], vector*), + const char *name, size_t nb_inputs, + size_t nb_vectors, u8 **vectors, size_t *sizes); #endif // UTILS_H