diff --git a/.gitignore b/.gitignore index 060b04a..0c0993c 100644 --- a/.gitignore +++ b/.gitignore @@ -44,6 +44,7 @@ tests/test_base64 tests/test_ctx tests/test_hash tests/test_jid +tests/test_rand tests/test_sasl tests/test_sock m4/ diff --git a/Makefile.am b/Makefile.am index 983fee1..d176f31 100644 --- a/Makefile.am +++ b/Makefile.am @@ -61,10 +61,14 @@ examples_component_LDADD = $(STROPHE_LIBS) ## Tests -TESTS = tests/check_parser -check_PROGRAMS = tests/check_parser +TESTS = tests/check_parser tests/test_rand +check_PROGRAMS = tests/check_parser tests/test_rand + tests_check_parser_SOURCES = tests/check_parser.c tests/test.h tests_check_parser_CFLAGS = @check_CFLAGS@ $(PARSER_CFLAGS) $(STROPHE_FLAGS) \ -I$(top_srcdir)/src tests_check_parser_LDADD = @check_LIBS@ $(STROPHE_LIBS) tests_check_parser_LDFLAGS = -static + +tests_test_rand_SOURCES = tests/test_rand.c src/sha1.c +tests_test_rand_CFLAGS = $(STROPHE_FLAGS) -I$(top_srcdir)/src diff --git a/tests/test_rand.c b/tests/test_rand.c new file mode 100644 index 0000000..b449712 --- /dev/null +++ b/tests/test_rand.c @@ -0,0 +1,193 @@ +/* check_rand.c + * strophe XMPP client library -- test vectors for Hash_DRBG + * + * Copyright (C) 2014 Dmitry Podgorny + * + * This software is provided AS-IS with no warranty, either express + * or implied. + * + * This software is distributed under license and may not be copied, + * modified or distributed except as expressly authorized under the + * terms of the license contained in the file LICENSE.txt in this + * distribution. + */ + +/* gcc -o test_rand -I. -I./src tests/test_rand.c src/sha1.c */ + +#include +#include +#include + +/* include rand.c to access private structures and functions */ +#include "rand.c" + +#ifndef ARRAY_SIZE +#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) +#endif + +/* stubs to build test without whole libstrophe */ +void *xmpp_alloc(const xmpp_ctx_t * const ctx, const size_t size) { + return NULL; +} +void xmpp_free(const xmpp_ctx_t * const ctx, void *p) { } +int xmpp_snprintf (char *str, size_t count, const char *fmt, ...) { + return 0; +} + +static struct { + const char *entropy_input; + const char *nonce; + size_t returned_bytes; + /* after instantiate */ + const char *V1; + const char *C1; + /* after first generate */ + const char *V2; + const char *C2; + /* after second generate */ + const char *V3; + const char *C3; + const char *output; +} test_vectors[] = { + { + .entropy_input = "136cf1c174e5a09f66b962d994396525", + .nonce = "fff1c6645f19231f", + .returned_bytes = 80, + .V1 = "a884a83fa40bcf730e7395dd5800ea7101b48" + "77aaa29da9b7bc0bd2bd052b9b4022f83bae3" + "8064134a233835845fdd1442bf3a0221bdc8", + .C1 = "4977fb1268c1f6286b5b3969d416fb8ca7e4e" + "aab7fd2edefc239202baa033f8b44e9145148" + "ad24ce83d597176a0bacc84c99246f15e088", + .V2 = "f1fca3520ccdc59b79cecf472c17e5fda9997" + "22629fcc88b3df9dd577a55f93f47189892b1" + "8e1c5f39dfc077ae256588eecec7bbd0323c", + .C2 = "4977fb1268c1f6286b5b3969d416fb8ca7e4e" + "aab7fd2edefc239202baa033f8b44e9145148" + "ad24ce83d597176a0bacc84c99246f15e088", + .V3 = "3b749e64758fbbc3e52a08b1002ee18a517e5" + "cd1a9cfb67b0032fd83245938ca8c01add770" + "68515bde248c75adea10bbaaf0bc18e66a2c", + .C3 = "4977fb1268c1f6286b5b3969d416fb8ca7e4e" + "aab7fd2edefc239202baa033f8b44e9145148" + "ad24ce83d597176a0bacc84c99246f15e088", + .output = "0e28130fa5ca11edd3293ca26fdb8ae1810611f7" + "8715082ed3841e7486f16677b28e33ffe0b93d98" + "ba57ba358c1343ab2a26b4eb7940f5bc63938464" + "1ee80a25140331076268bd1ce702ad534dda0ed8", + }, + + { + .entropy_input = "dfed69b08902fcfb795d5d35dbe23f6b", + .nonce = "37258e820432e392", + .returned_bytes = 80, + .V1 = "2708022f0f6d13cd8bc139ceb86ee237ee124" + "e17029ac4f053d41526285599d4eac5029972" + "7d83a0df0d5fa9824d5f14d7e7e9c8bdb165", + .C1 = "fdb1a827c30e436c997261da6dc31ae7c27ee" + "28e5c29b2ee0ca57b44ab78b7b0d1e8b459ba" + "7285f5d93abf218d16d834a803c2330321cd", + .V2 = "24b9aa56d27b573a25339ba92631fd1fb0913" + "0a55ec477de6079906ad3ce5185bcadb7b047" + "627060f80afb8529c18b46567e6b79dffb01", + .C2 = "fdb1a827c30e436c997261da6dc31ae7c27ee" + "28e5c29b2ee0ca57b44ab78b7b0d1e8b459ba" + "7285f5d93abf218d16d834a803c2330321cd", + .V3 = "226b527e95899aa6bea5fd8393f5180773101" + "333baee2acc6d1f0baf7f4709368e966c945c" + "d4a0d86093183375443379b09c08e4381fa8", + .C3 = "fdb1a827c30e436c997261da6dc31ae7c27ee" + "28e5c29b2ee0ca57b44ab78b7b0d1e8b459ba" + "7285f5d93abf218d16d834a803c2330321cd", + .output = "adcb8e2cbbc5957d538a20db18b5e7fe350a90a2" + "01359fab9e0f154c53aa146bc6af1fcc7ff8f330" + "b8d9f3d7b038488ba627e6fa21d0147377b13404" + "22b22634b412dac69ac82c35b5fb411a4e42a133", + }, +}; + +static uint8_t char_to_bin(char c) +{ + return c <= '9' ? (uint8_t)(c - '0') : + c <= 'Z' ? (uint8_t)(c - 'A' + 10) : + (uint8_t)(c - 'a' + 10); +} + +static void hex_to_bin(const char *hex, uint8_t *bin, size_t *bin_len) +{ + size_t len = strlen(hex); + size_t i; + + assert(len % 2 == 0); + + for (i = 0; i < len / 2; ++i) { + bin[i] = char_to_bin(hex[i * 2]) * 16 + char_to_bin(hex[i * 2 + 1]); + } + *bin_len = len / 2; +} + +static const char *bin_to_hex(uint8_t *bin, size_t len) +{ + static char buf[1024]; + size_t i; + + assert(ARRAY_SIZE(buf) > len * 2); + + for (i = 0; i < len; ++i) { + sprintf(buf + i * 2, "%02x", bin[i]); + } + + return buf; +} + +#define COMPARE(v1, v2) \ +do { \ + const char *__v1 = v1; \ + const char *__v2 = v2; \ + if (strcmp(__v1, __v2) != 0) { \ + printf("%s differs!\n" \ + "expected: %s\n" \ + "got: %s\n", \ + #v1, __v1, __v2); \ + exit(1); \ + } \ +} while (0) + +int main() +{ + size_t i; + uint8_t entropy_input[1024]; + size_t entropy_input_len; + uint8_t nonce[1024]; + size_t nonce_len; + uint8_t output[1024]; + Hash_DRBG_CTX ctx; + + for (i = 0; i < ARRAY_SIZE(test_vectors); ++i) { + printf("Test #%d: ", (int)i + 1); + hex_to_bin(test_vectors[i].entropy_input, entropy_input, + &entropy_input_len); + hex_to_bin(test_vectors[i].nonce, nonce, &nonce_len); + + Hash_DRBG_Instantiate(&ctx, entropy_input, entropy_input_len, + nonce, nonce_len); + COMPARE(test_vectors[i].V1, bin_to_hex(ctx.V, sizeof(ctx.V))); + COMPARE(test_vectors[i].C1, bin_to_hex(ctx.C, sizeof(ctx.C))); + assert(ctx.reseed_counter == 1); + + Hash_DRBG_Generate(&ctx, output, test_vectors[i].returned_bytes); + COMPARE(test_vectors[i].V2, bin_to_hex(ctx.V, sizeof(ctx.V))); + COMPARE(test_vectors[i].C2, bin_to_hex(ctx.C, sizeof(ctx.C))); + assert(ctx.reseed_counter == 2); + + Hash_DRBG_Generate(&ctx, output, test_vectors[i].returned_bytes); + COMPARE(test_vectors[i].V3, bin_to_hex(ctx.V, sizeof(ctx.V))); + COMPARE(test_vectors[i].C3, bin_to_hex(ctx.C, sizeof(ctx.C))); + COMPARE(test_vectors[i].output, + bin_to_hex(output, test_vectors[i].returned_bytes)); + assert(ctx.reseed_counter == 3); + printf("ok\n"); + } + + return 0; +}