From c1663a74215f560def4f24492b881765b5b64fd5 Mon Sep 17 00:00:00 2001 From: Nikos Mavrogiannopoulos Date: Sat, 9 Jul 2016 14:52:42 +0200 Subject: tests: added unit testing for DTLS sliding window implementation This was taken from the unit testing of AF_KTLS. --- configure.ac | 3 + tests/Makefile.am | 5 + tests/dtls-sliding-window.c | 497 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 505 insertions(+) create mode 100644 tests/dtls-sliding-window.c diff --git a/configure.ac b/configure.ac index f2f08c0624..b8e6bbad6b 100644 --- a/configure.ac +++ b/configure.ac @@ -415,6 +415,9 @@ if [ test "$enable_fips" = "yes" ];then fi fi +PKG_CHECK_MODULES(CMOCKA, cmocka, [with_cmocka=yes], [with_cmocka=no]) +AM_CONDITIONAL(HAVE_CMOCKA, test "$with_cmocka" != "no") + AC_ARG_WITH(idn, AS_HELP_STRING([--without-idn], [disable support for libidn]), try_libidn="$withval", diff --git a/tests/Makefile.am b/tests/Makefile.am index 72b1bf35c1..fab1fb7394 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -114,6 +114,11 @@ if HAVE_SECCOMP_TESTS ctests += dtls-with-seccomp tls-with-seccomp dtls-client-with-seccomp tls-client-with-seccomp endif +if HAVE_CMOCKA +LDADD += $(CMOCKA_LIBS) +ctests += dtls-sliding-window +endif + mini_dtls_pthread_LDADD = $(LDADD) -lpthread # These tests need gnulib for memmem() diff --git a/tests/dtls-sliding-window.c b/tests/dtls-sliding-window.c new file mode 100644 index 0000000000..eeec757c98 --- /dev/null +++ b/tests/dtls-sliding-window.c @@ -0,0 +1,497 @@ +/* + * Copyright (C) 2016 Red Hat, Inc. + * + * Author: Nikos Mavrogiannopoulos + * + * This file is part of GnuTLS. + * + * GnuTLS is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * GnuTLS is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GnuTLS; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +/* Unit test for DTLS window handling */ + +#define LARGE_INT 4194304 +#define INT_OVER_32_BITS 281474976708836LL + +struct record_parameters_st { + uint64_t dtls_sw_bits; + uint64_t dtls_sw_start; + unsigned dtls_sw_have_recv; + unsigned epoch; +}; + +typedef struct { + unsigned char i[8]; +} uint64; +#define gnutls_assert_val(x) x + +void _dtls_reset_window(struct record_parameters_st *rp); +int _dtls_record_check(struct record_parameters_st *rp, uint64 * _seq); + +/* taken from nettle */ +#ifdef WORDS_BIGENDIAN +# define BSWAP64(x) x +#else +# define BSWAP64(x) \ + ((((uint64_t)(x) & 0xff) << 56) \ + | (((uint64_t)(x) & 0xff00) << 40) \ + | (((uint64_t)(x) & 0xff0000) << 24) \ + | (((uint64_t)(x) & 0xff000000) << 8) \ + | (((uint64_t)(x) >> 8) & 0xff000000) \ + | (((uint64_t)(x) >> 24) & 0xff0000) \ + | (((uint64_t)(x) >> 40) & 0xff00) \ + | ((uint64_t)(x) >> 56) ) +#endif + +#define DTLS_SW_NO_INCLUDES +#include "../lib/dtls-sw.c" + +static void uint64_set(uint64* t, uint64_t v) +{ + memcpy(t->i, &v, 8); +} + +#define RESET_WINDOW \ + memset(&state, 0, sizeof(state)) + +#define SET_WINDOW_START(x) \ + state.dtls_sw_start = ((x)&DTLS_SEQ_NUM_MASK) + +#define SET_WINDOW_LAST_RECV(x) \ + uint64_set(&t, BSWAP64(x)); \ + state.dtls_sw_have_recv = 1 + +static void check_dtls_window_uninit_0(void **glob_state) +{ + struct record_parameters_st state; + uint64 t; + + RESET_WINDOW; + SET_WINDOW_START(0); + + uint64_set(&t, 0); + + assert_int_equal(_dtls_record_check(&state, &t), 0); +} + +static void check_dtls_window_uninit_large(void **glob_state) +{ + struct record_parameters_st state; + uint64 t; + + RESET_WINDOW; + + uint64_set(&t, BSWAP64(LARGE_INT+1+64)); + + assert_int_equal(_dtls_record_check(&state, &t), 0); +} + +static void check_dtls_window_uninit_very_large(void **glob_state) +{ + struct record_parameters_st state; + uint64 t; + + RESET_WINDOW; + + uint64_set(&t, BSWAP64(INT_OVER_32_BITS)); + + assert_int_equal(_dtls_record_check(&state, &t), 0); +} + +static void check_dtls_window_12(void **glob_state) +{ + struct record_parameters_st state; + uint64 t; + + RESET_WINDOW; + SET_WINDOW_START(0); + SET_WINDOW_LAST_RECV(1); + + uint64_set(&t, BSWAP64(2)); + + assert_int_equal(_dtls_record_check(&state, &t), 0); +} + +static void check_dtls_window_19(void **glob_state) +{ + struct record_parameters_st state; + uint64 t; + + RESET_WINDOW; + SET_WINDOW_START(0); + SET_WINDOW_LAST_RECV(1); + + uint64_set(&t, BSWAP64(9)); + + assert_int_equal(_dtls_record_check(&state, &t), 0); +} + +static void check_dtls_window_21(void **glob_state) +{ + struct record_parameters_st state; + uint64 t; + + RESET_WINDOW; + SET_WINDOW_START(0); + SET_WINDOW_LAST_RECV(2); + + uint64_set(&t, BSWAP64(1)); + + assert_int_equal(_dtls_record_check(&state, &t), 0); +} + +static void check_dtls_window_91(void **glob_state) +{ + struct record_parameters_st state; + uint64 t; + + RESET_WINDOW; + SET_WINDOW_START(0); + SET_WINDOW_LAST_RECV(9); + + uint64_set(&t, BSWAP64(1)); + + assert_int_equal(_dtls_record_check(&state, &t), 0); +} + +static void check_dtls_window_large_21(void **glob_state) +{ + struct record_parameters_st state; + uint64 t; + + RESET_WINDOW; + SET_WINDOW_START(LARGE_INT); + SET_WINDOW_LAST_RECV(LARGE_INT+2); + + uint64_set(&t, BSWAP64(LARGE_INT+1)); + + assert_int_equal(_dtls_record_check(&state, &t), 0); +} + +static void check_dtls_window_large_12(void **glob_state) +{ + struct record_parameters_st state; + uint64 t; + + RESET_WINDOW; + SET_WINDOW_START(LARGE_INT); + SET_WINDOW_LAST_RECV(LARGE_INT+1); + + uint64_set(&t, BSWAP64(LARGE_INT+2)); + + assert_int_equal(_dtls_record_check(&state, &t), 0); +} + +static void check_dtls_window_large_91(void **glob_state) +{ + struct record_parameters_st state; + uint64 t; + + RESET_WINDOW; + SET_WINDOW_START(LARGE_INT); + SET_WINDOW_LAST_RECV(LARGE_INT+9); + + uint64_set(&t, BSWAP64(LARGE_INT+1)); + + assert_int_equal(_dtls_record_check(&state, &t), 0); +} + +static void check_dtls_window_large_19(void **glob_state) +{ + struct record_parameters_st state; + uint64 t; + + RESET_WINDOW; + SET_WINDOW_START(LARGE_INT); + SET_WINDOW_LAST_RECV(LARGE_INT+1); + + uint64_set(&t, BSWAP64(LARGE_INT+9)); + + assert_int_equal(_dtls_record_check(&state, &t), 0); +} + +static void check_dtls_window_very_large_12(void **glob_state) +{ + struct record_parameters_st state; + uint64 t; + + RESET_WINDOW; + SET_WINDOW_START(INT_OVER_32_BITS); + SET_WINDOW_LAST_RECV(INT_OVER_32_BITS+1); + + uint64_set(&t, BSWAP64(INT_OVER_32_BITS+2)); + + assert_int_equal(_dtls_record_check(&state, &t), 0); +} + +static void check_dtls_window_very_large_91(void **glob_state) +{ + struct record_parameters_st state; + uint64 t; + + RESET_WINDOW; + SET_WINDOW_START(INT_OVER_32_BITS); + SET_WINDOW_LAST_RECV(INT_OVER_32_BITS+9); + + uint64_set(&t, BSWAP64(INT_OVER_32_BITS+1)); + + assert_int_equal(_dtls_record_check(&state, &t), 0); +} + +static void check_dtls_window_very_large_19(void **glob_state) +{ + struct record_parameters_st state; + uint64 t; + + RESET_WINDOW; + SET_WINDOW_START(INT_OVER_32_BITS); + SET_WINDOW_LAST_RECV(INT_OVER_32_BITS+1); + + uint64_set(&t, BSWAP64(INT_OVER_32_BITS+9)); + + assert_int_equal(_dtls_record_check(&state, &t), 0); +} + +static void check_dtls_window_outside(void **glob_state) +{ + struct record_parameters_st state; + uint64 t; + + RESET_WINDOW; + SET_WINDOW_START(0); + SET_WINDOW_LAST_RECV(1); + + uint64_set(&t, BSWAP64(1+64)); + + assert_int_equal(_dtls_record_check(&state, &t), -2); +} + +static void check_dtls_window_large_outside(void **glob_state) +{ + struct record_parameters_st state; + uint64 t; + + RESET_WINDOW; + SET_WINDOW_START(LARGE_INT); + SET_WINDOW_LAST_RECV(LARGE_INT+1); + + uint64_set(&t, BSWAP64(LARGE_INT+1+64)); + + assert_int_equal(_dtls_record_check(&state, &t), -2); +} + +static void check_dtls_window_very_large_outside(void **glob_state) +{ + struct record_parameters_st state; + uint64 t; + + RESET_WINDOW; + SET_WINDOW_START(INT_OVER_32_BITS); + SET_WINDOW_LAST_RECV(INT_OVER_32_BITS+1); + + uint64_set(&t, BSWAP64(INT_OVER_32_BITS+1+64)); + + assert_int_equal(_dtls_record_check(&state, &t), -2); +} + +static void check_dtls_window_dup1(void **glob_state) +{ + struct record_parameters_st state; + uint64 t; + + RESET_WINDOW; + SET_WINDOW_START(LARGE_INT-1); + SET_WINDOW_LAST_RECV(LARGE_INT); + + uint64_set(&t, BSWAP64(LARGE_INT)); + assert_int_equal(_dtls_record_check(&state, &t), 0); + + uint64_set(&t, BSWAP64(LARGE_INT+1)); + assert_int_equal(_dtls_record_check(&state, &t), 0); + + uint64_set(&t, BSWAP64(LARGE_INT+16)); + assert_int_equal(_dtls_record_check(&state, &t), 0); + + uint64_set(&t, BSWAP64(LARGE_INT+1)); + assert_int_equal(_dtls_record_check(&state, &t), -2); +} + +static void check_dtls_window_dup2(void **glob_state) +{ + struct record_parameters_st state; + uint64 t; + + RESET_WINDOW; + SET_WINDOW_START(LARGE_INT-1); + SET_WINDOW_LAST_RECV(LARGE_INT); + + uint64_set(&t, BSWAP64(LARGE_INT)); + assert_int_equal(_dtls_record_check(&state, &t), 0); + + uint64_set(&t, BSWAP64(LARGE_INT+16)); + assert_int_equal(_dtls_record_check(&state, &t), 0); + + uint64_set(&t, BSWAP64(LARGE_INT+1)); + assert_int_equal(_dtls_record_check(&state, &t), 0); + + uint64_set(&t, BSWAP64(LARGE_INT+16)); + assert_int_equal(_dtls_record_check(&state, &t), -3); +} + +static void check_dtls_window_dup3(void **glob_state) +{ + struct record_parameters_st state; + uint64 t; + + RESET_WINDOW; + SET_WINDOW_START(LARGE_INT-1); + SET_WINDOW_LAST_RECV(LARGE_INT); + + uint64_set(&t, BSWAP64(LARGE_INT)); + assert_int_equal(_dtls_record_check(&state, &t), 0); + + uint64_set(&t, BSWAP64(LARGE_INT+16)); + assert_int_equal(_dtls_record_check(&state, &t), 0); + + uint64_set(&t, BSWAP64(LARGE_INT+15)); + assert_int_equal(_dtls_record_check(&state, &t), 0); + + uint64_set(&t, BSWAP64(LARGE_INT+14)); + assert_int_equal(_dtls_record_check(&state, &t), 0); + + uint64_set(&t, BSWAP64(LARGE_INT+5)); + assert_int_equal(_dtls_record_check(&state, &t), 0); + + uint64_set(&t, BSWAP64(LARGE_INT+5)); + assert_int_equal(_dtls_record_check(&state, &t), -3); +} + +static void check_dtls_window_out_of_order(void **glob_state) +{ + struct record_parameters_st state; + uint64 t; + + RESET_WINDOW; + SET_WINDOW_START(LARGE_INT-1); + SET_WINDOW_LAST_RECV(LARGE_INT); + + uint64_set(&t, BSWAP64(LARGE_INT)); + assert_int_equal(_dtls_record_check(&state, &t), 0); + + uint64_set(&t, BSWAP64(LARGE_INT+8)); + assert_int_equal(_dtls_record_check(&state, &t), 0); + + uint64_set(&t, BSWAP64(LARGE_INT+7)); + assert_int_equal(_dtls_record_check(&state, &t), 0); + + uint64_set(&t, BSWAP64(LARGE_INT+6)); + assert_int_equal(_dtls_record_check(&state, &t), 0); + + uint64_set(&t, BSWAP64(LARGE_INT+5)); + assert_int_equal(_dtls_record_check(&state, &t), 0); + + uint64_set(&t, BSWAP64(LARGE_INT+4)); + assert_int_equal(_dtls_record_check(&state, &t), 0); + + uint64_set(&t, BSWAP64(LARGE_INT+3)); + assert_int_equal(_dtls_record_check(&state, &t), 0); + + uint64_set(&t, BSWAP64(LARGE_INT+2)); + assert_int_equal(_dtls_record_check(&state, &t), 0); + + uint64_set(&t, BSWAP64(LARGE_INT+1)); + assert_int_equal(_dtls_record_check(&state, &t), 0); + + uint64_set(&t, BSWAP64(LARGE_INT+9)); + assert_int_equal(_dtls_record_check(&state, &t), 0); +} + +static void check_dtls_window_epoch_higher(void **glob_state) +{ + struct record_parameters_st state; + uint64 t; + + RESET_WINDOW; + SET_WINDOW_START(LARGE_INT-1); + SET_WINDOW_LAST_RECV(LARGE_INT); + + uint64_set(&t, BSWAP64(LARGE_INT)); + assert_int_equal(_dtls_record_check(&state, &t), 0); + + uint64_set(&t, BSWAP64((LARGE_INT+8)|0x1000000000000LL)); + assert_int_equal(_dtls_record_check(&state, &t), -1); +} + +static void check_dtls_window_epoch_lower(void **glob_state) +{ + struct record_parameters_st state; + uint64 t; + + RESET_WINDOW; + uint64_set(&t, BSWAP64(0x1000000000000LL)); + + state.epoch = 1; + SET_WINDOW_START(0x1000000000000LL); + SET_WINDOW_LAST_RECV((0x1000000000000LL) + 1); + + uint64_set(&t, BSWAP64(2 | 0x1000000000000LL)); + assert_int_equal(_dtls_record_check(&state, &t), 0); + + uint64_set(&t, BSWAP64(3 | 0x1000000000000LL)); + assert_int_equal(_dtls_record_check(&state, &t), 0); + + uint64_set(&t, BSWAP64(5)); + assert_int_equal(_dtls_record_check(&state, &t), -1); +} + + +int main(void) +{ + const struct CMUnitTest tests[] = { + cmocka_unit_test(check_dtls_window_uninit_0), + cmocka_unit_test(check_dtls_window_uninit_large), + cmocka_unit_test(check_dtls_window_uninit_very_large), + cmocka_unit_test(check_dtls_window_12), + cmocka_unit_test(check_dtls_window_21), + cmocka_unit_test(check_dtls_window_19), + cmocka_unit_test(check_dtls_window_91), + cmocka_unit_test(check_dtls_window_large_21), + cmocka_unit_test(check_dtls_window_large_12), + cmocka_unit_test(check_dtls_window_large_19), + cmocka_unit_test(check_dtls_window_large_91), + cmocka_unit_test(check_dtls_window_dup1), + cmocka_unit_test(check_dtls_window_dup2), + cmocka_unit_test(check_dtls_window_dup3), + cmocka_unit_test(check_dtls_window_outside), + cmocka_unit_test(check_dtls_window_large_outside), + cmocka_unit_test(check_dtls_window_out_of_order), + cmocka_unit_test(check_dtls_window_epoch_lower), + cmocka_unit_test(check_dtls_window_epoch_higher), + cmocka_unit_test(check_dtls_window_very_large_12), + cmocka_unit_test(check_dtls_window_very_large_19), + cmocka_unit_test(check_dtls_window_very_large_91), + cmocka_unit_test(check_dtls_window_very_large_outside) + }; + return cmocka_run_group_tests(tests, NULL, NULL); +} -- cgit v1.2.1