Message ID | 20170817141546.31426-2-christian.storm@siemens.com |
---|---|
State | Accepted |
Delegated to: | Stefano Babic |
Headers | show |
On 17/08/2017 16:15, Christian Storm wrote: > Signed-off-by: Christian Storm <christian.storm@siemens.com> > --- > Makefile | 7 ++- > corelib/test/Makefile | 64 ++++++++++++++++++++ > corelib/test/test_crypt.c | 148 ++++++++++++++++++++++++++++++++++++++++++++++ > 3 files changed, 218 insertions(+), 1 deletion(-) > create mode 100644 corelib/test/Makefile > create mode 100644 corelib/test/test_crypt.c > > diff --git a/Makefile b/Makefile > index 0edb03a..92cc500 100644 > --- a/Makefile > +++ b/Makefile > @@ -406,7 +406,8 @@ install: all > PHONY += run-tests > tests: \ > acceptance-tests \ > - suricatta-tests > + suricatta-tests \ > + corelib-tests > > PHONY += acceptance-tests > acceptance-tests: FORCE > @@ -416,6 +417,10 @@ PHONY += suricatta-tests > suricatta-tests: FORCE > $(Q)$(MAKE) $(build)=suricatta/test SWOBJS="$(swupdate-objs)" SWLIBS="$(swupdate-libs)" LDLIBS="$(LDLIBS)" tests > > +PHONY += corelib-tests > +corelib-tests: FORCE > + $(Q)$(MAKE) $(build)=corelib/test SWOBJS="$(swupdate-objs)" SWLIBS="$(swupdate-libs)" LDLIBS="$(LDLIBS)" tests > + > # The actual objects are generated when descending, > # make sure no implicit rule kicks in > $(sort $(swupdate-all)): $(swupdate-dirs) ; > diff --git a/corelib/test/Makefile b/corelib/test/Makefile > new file mode 100644 > index 0000000..b071177 > --- /dev/null > +++ b/corelib/test/Makefile > @@ -0,0 +1,64 @@ > +## Author: Christian Storm > +## Copyright (C) 2017, Siemens AG > +## > +## This program 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 2 of > +## the License, or (at your option) any later version. > +## > +## This program 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 this program; if not, write to the Free Software > +## Foundation, Inc. > + > +tests-$(CONFIG_ENCRYPTED_IMAGES) += test_crypt > + > +ccflags-y += -I$(src)/../ > + > +TARGETS = $(addprefix $(obj)/, $(tests-y)) > +tests-objs = $(addsuffix .o, $(TARGETS)) > +tests-lnk = $(addsuffix .lnk, $(TARGETS)) > +targets += $(addsuffix .o, $(tests-y)) > + > +ifneq ($(CONFIG_EXTRA_LDFLAGS),) > +EXTRA_LDFLAGS += $(strip $(subst ",,$(CONFIG_EXTRA_LDFLAGS)))#")) > +endif > + > +## transfer __mock_*() functions to according linker flags via rudimentary regex awk parsing > +LDMOCKS = `/usr/bin/awk '/^[^(extern)|(static)]*([\*_[:alnum:]]+[[:blank:]]+)+[\*]*__wrap_/{where = match($$0,"__wrap_[_[:alnum:]]+"); if (RSTART > 0) { print "-Wl,--wrap=" substr($$0, RSTART+7, RLENGTH-7);}}' $(basename $@).c` > + > +quiet_cmd_linktestexe = LD $(basename $@) > + cmd_linktestexe = $(srctree)/scripts/trylink \ > + "$(basename $@)" \ > + "$(CC)" \ > + "$(KBUILD_CFLAGS)" \ > + "$(LDFLAGS) $(EXTRA_LDFLAGS) $(LDMOCKS)" \ > + "$(basename $@).o $(subst core/built-in.o,core/built-in.o.tmp,$(SWOBJS))" \ > + "$(SWLIBS)" \ > + "$(LDLIBS) cmocka" > + > +EXECUTE_TEST = echo "RUN $(subst $(obj)/,,$(var))"; CMOCKA_MESSAGE_OUTPUT=TAP $(var) > + > +PHONY += default > +default: > + $(info please run 'make corelib-tests' in swupdate main directory) > + > +PHONY += tests > +ifneq "$(tests-y)" "" > +tests: $(tests-objs) $(tests-lnk) > + @+$(foreach var,$(TARGETS),$(EXECUTE_TEST);) > +else > +tests: > + @$(info crypto functions are disabled, nothing to test.) > + @: > +endif > + > +$(obj)/%.lnk: $(objtree)/core/built-in.o > + $(Q)strip -N main -o $(objtree)/core/built-in.o.tmp $(objtree)/core/built-in.o > + $(Q)$(call cmd,linktestexe) > + > +.PHONY: $(PHONY) > diff --git a/corelib/test/test_crypt.c b/corelib/test/test_crypt.c > new file mode 100644 > index 0000000..84ac6ed > --- /dev/null > +++ b/corelib/test/test_crypt.c > @@ -0,0 +1,148 @@ > +/* > + * Author: Christian Storm > + * Copyright (C) 2017, Siemens AG > + * > + * This program 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 2 of > + * the License, or (at your option) any later version. > + * > + * This program 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 this program; if not, write to the Free Software > + * Foundation, Inc. > + */ > + > +#include <stdlib.h> > +#include <stdarg.h> > +#include <stddef.h> > +#include <setjmp.h> > +#include <cmocka.h> > +#include <util.h> > +#include <sslapi.h> > + > +struct cryptdata { > + unsigned char *key; > + unsigned char *iv; > + unsigned char *salt; > + unsigned char *crypttext; > +}; > + > +static void hex2bin(unsigned char *dest, const unsigned char *source) > +{ > + unsigned int val; > + for (unsigned int i = 0; i < strlen((const char *)source); i += 2) { > + val = from_ascii((const char *)&source[i], 2, LG_16); > + dest[i / 2] = val; > + } > +} > + > +static void do_crypt(struct cryptdata *crypt, unsigned char *CRYPTTEXT, unsigned char *PLAINTEXT) > +{ > + int len; > + void *dcrypt = swupdate_DECRYPT_init(crypt->key, crypt->iv, crypt->salt); > + assert_non_null(dcrypt); > + > + unsigned char *buffer = calloc(1, strlen((const char *)CRYPTTEXT) + EVP_MAX_BLOCK_LENGTH); > + int ret = swupdate_DECRYPT_update(dcrypt, buffer, &len, crypt->crypttext, strlen((const char *)CRYPTTEXT) / 2); > + assert_true(ret >= 0); > + assert_true(len == 0); > + > + ret = swupdate_DECRYPT_final(dcrypt, crypt->crypttext, &len); > + assert_true(ret == 0); > + assert_true(len == (int)strlen((const char *)PLAINTEXT)); > + assert_true(strncmp((const char *)buffer, (const char *)PLAINTEXT, len) == 0); > + free(buffer); > +} > + > +static void test_crypt_nosalt(void **state) > +{ > + (void)state; > + > + unsigned char KEY[] = "E5E9FA1BA31ECD1AE84F75CAAA474F3A663F05F412028F81DA65D26EE56424B2"; > + unsigned char IV[] = "E93DA465B309C53FEC5FF93C9637DA58"; > + unsigned char CRYPTTEXT[] = "E4B7745CA14039555CECD548BB33E0C3"; > + unsigned char PLAINTEXT[] = "CRYPTTEST"; > + > + struct cryptdata crypt; > + hex2bin((crypt.key = calloc(1, strlen((const char *)KEY))), KEY); > + hex2bin((crypt.iv = calloc(1, strlen((const char *)IV))), IV); > + crypt.salt = NULL; > + hex2bin((crypt.crypttext = calloc(1, strlen((const char *)CRYPTTEXT))), CRYPTTEXT); > + > + do_crypt(&crypt, &CRYPTTEXT[0], &PLAINTEXT[0]); > + > + free(crypt.key); > + free(crypt.iv); > + free(crypt.crypttext); > +} > + > +static void test_crypt_salt(void **state) > +{ > + (void)state; > + > + unsigned char KEY[] = "69D54287F856D30B51B812FDF714556778CF31E1B104D9C68BD90C669C37D1AB"; > + unsigned char IV[] = "E7039ABFCA63EB8EB1D320F7918275B2"; > + unsigned char SALT[] = "F75A9C11F7F63C08"; > + unsigned char CRYPTTEXT[] = "A17EBBB1A28459352FE3A994404E35AA"; > + unsigned char PLAINTEXT[] = "CRYPTTEST"; > + > + struct cryptdata crypt; > + hex2bin((crypt.key = calloc(1, strlen((const char *)KEY))), KEY); > + hex2bin((crypt.iv = calloc(1, strlen((const char *)IV))), IV); > + hex2bin((crypt.salt = calloc(1, strlen((const char *)SALT))), SALT); > + hex2bin((crypt.crypttext = calloc(1, strlen((const char *)CRYPTTEXT))), CRYPTTEXT); > + > + do_crypt(&crypt, &CRYPTTEXT[0], &PLAINTEXT[0]); > + > + free(crypt.key); > + free(crypt.iv); > + free(crypt.salt); > + free(crypt.crypttext); > +} > + > +static void test_crypt_failure(void **state) > +{ > + (void)state; > + > + unsigned char KEY[] = "E5E9FA1BA31ECD1AE84F75CAAA474F3A663F05F412028F81DA65D26EE56424B2"; > + unsigned char IV[] = "E93DA465B309C53FEC5FF93C9637DA58"; > + unsigned char CRYPTTEXT[] = "CAFECAFECAFECAFECAFECAFECAFECAFE"; > + > + struct cryptdata crypt; > + hex2bin((crypt.key = calloc(1, strlen((const char *)KEY))), KEY); > + hex2bin((crypt.iv = calloc(1, strlen((const char *)IV))), IV); > + crypt.salt = NULL; > + hex2bin((crypt.crypttext = calloc(1, strlen((const char *)CRYPTTEXT))), CRYPTTEXT); > + > + int len; > + void *dcrypt = swupdate_DECRYPT_init(crypt.key, crypt.iv, crypt.salt); > + assert_non_null(dcrypt); > + > + unsigned char *buffer = calloc(1, strlen((const char *)CRYPTTEXT) + EVP_MAX_BLOCK_LENGTH); > + int ret = swupdate_DECRYPT_update(dcrypt, buffer, &len, crypt.crypttext, strlen((const char *)CRYPTTEXT) / 2); > + ret = swupdate_DECRYPT_final(dcrypt, crypt.crypttext, &len); > + assert_true(ret != 0); > + free(buffer); > + > + free(crypt.key); > + free(crypt.iv); > + free(crypt.salt); > + free(crypt.crypttext); > +} > + > +int main(void) > +{ > + int error_count = 0; > + const struct CMUnitTest crypt_tests[] = { > + cmocka_unit_test(test_crypt_nosalt), > + cmocka_unit_test(test_crypt_failure), > + cmocka_unit_test(test_crypt_salt) > + }; > + error_count += cmocka_run_group_tests_name("crypt", crypt_tests, NULL, NULL); > + return error_count; > +} > Applied to -master, thanks ! Best regards, Stefano Babic
diff --git a/Makefile b/Makefile index 0edb03a..92cc500 100644 --- a/Makefile +++ b/Makefile @@ -406,7 +406,8 @@ install: all PHONY += run-tests tests: \ acceptance-tests \ - suricatta-tests + suricatta-tests \ + corelib-tests PHONY += acceptance-tests acceptance-tests: FORCE @@ -416,6 +417,10 @@ PHONY += suricatta-tests suricatta-tests: FORCE $(Q)$(MAKE) $(build)=suricatta/test SWOBJS="$(swupdate-objs)" SWLIBS="$(swupdate-libs)" LDLIBS="$(LDLIBS)" tests +PHONY += corelib-tests +corelib-tests: FORCE + $(Q)$(MAKE) $(build)=corelib/test SWOBJS="$(swupdate-objs)" SWLIBS="$(swupdate-libs)" LDLIBS="$(LDLIBS)" tests + # The actual objects are generated when descending, # make sure no implicit rule kicks in $(sort $(swupdate-all)): $(swupdate-dirs) ; diff --git a/corelib/test/Makefile b/corelib/test/Makefile new file mode 100644 index 0000000..b071177 --- /dev/null +++ b/corelib/test/Makefile @@ -0,0 +1,64 @@ +## Author: Christian Storm +## Copyright (C) 2017, Siemens AG +## +## This program 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 2 of +## the License, or (at your option) any later version. +## +## This program 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 this program; if not, write to the Free Software +## Foundation, Inc. + +tests-$(CONFIG_ENCRYPTED_IMAGES) += test_crypt + +ccflags-y += -I$(src)/../ + +TARGETS = $(addprefix $(obj)/, $(tests-y)) +tests-objs = $(addsuffix .o, $(TARGETS)) +tests-lnk = $(addsuffix .lnk, $(TARGETS)) +targets += $(addsuffix .o, $(tests-y)) + +ifneq ($(CONFIG_EXTRA_LDFLAGS),) +EXTRA_LDFLAGS += $(strip $(subst ",,$(CONFIG_EXTRA_LDFLAGS)))#")) +endif + +## transfer __mock_*() functions to according linker flags via rudimentary regex awk parsing +LDMOCKS = `/usr/bin/awk '/^[^(extern)|(static)]*([\*_[:alnum:]]+[[:blank:]]+)+[\*]*__wrap_/{where = match($$0,"__wrap_[_[:alnum:]]+"); if (RSTART > 0) { print "-Wl,--wrap=" substr($$0, RSTART+7, RLENGTH-7);}}' $(basename $@).c` + +quiet_cmd_linktestexe = LD $(basename $@) + cmd_linktestexe = $(srctree)/scripts/trylink \ + "$(basename $@)" \ + "$(CC)" \ + "$(KBUILD_CFLAGS)" \ + "$(LDFLAGS) $(EXTRA_LDFLAGS) $(LDMOCKS)" \ + "$(basename $@).o $(subst core/built-in.o,core/built-in.o.tmp,$(SWOBJS))" \ + "$(SWLIBS)" \ + "$(LDLIBS) cmocka" + +EXECUTE_TEST = echo "RUN $(subst $(obj)/,,$(var))"; CMOCKA_MESSAGE_OUTPUT=TAP $(var) + +PHONY += default +default: + $(info please run 'make corelib-tests' in swupdate main directory) + +PHONY += tests +ifneq "$(tests-y)" "" +tests: $(tests-objs) $(tests-lnk) + @+$(foreach var,$(TARGETS),$(EXECUTE_TEST);) +else +tests: + @$(info crypto functions are disabled, nothing to test.) + @: +endif + +$(obj)/%.lnk: $(objtree)/core/built-in.o + $(Q)strip -N main -o $(objtree)/core/built-in.o.tmp $(objtree)/core/built-in.o + $(Q)$(call cmd,linktestexe) + +.PHONY: $(PHONY) diff --git a/corelib/test/test_crypt.c b/corelib/test/test_crypt.c new file mode 100644 index 0000000..84ac6ed --- /dev/null +++ b/corelib/test/test_crypt.c @@ -0,0 +1,148 @@ +/* + * Author: Christian Storm + * Copyright (C) 2017, Siemens AG + * + * This program 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 2 of + * the License, or (at your option) any later version. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc. + */ + +#include <stdlib.h> +#include <stdarg.h> +#include <stddef.h> +#include <setjmp.h> +#include <cmocka.h> +#include <util.h> +#include <sslapi.h> + +struct cryptdata { + unsigned char *key; + unsigned char *iv; + unsigned char *salt; + unsigned char *crypttext; +}; + +static void hex2bin(unsigned char *dest, const unsigned char *source) +{ + unsigned int val; + for (unsigned int i = 0; i < strlen((const char *)source); i += 2) { + val = from_ascii((const char *)&source[i], 2, LG_16); + dest[i / 2] = val; + } +} + +static void do_crypt(struct cryptdata *crypt, unsigned char *CRYPTTEXT, unsigned char *PLAINTEXT) +{ + int len; + void *dcrypt = swupdate_DECRYPT_init(crypt->key, crypt->iv, crypt->salt); + assert_non_null(dcrypt); + + unsigned char *buffer = calloc(1, strlen((const char *)CRYPTTEXT) + EVP_MAX_BLOCK_LENGTH); + int ret = swupdate_DECRYPT_update(dcrypt, buffer, &len, crypt->crypttext, strlen((const char *)CRYPTTEXT) / 2); + assert_true(ret >= 0); + assert_true(len == 0); + + ret = swupdate_DECRYPT_final(dcrypt, crypt->crypttext, &len); + assert_true(ret == 0); + assert_true(len == (int)strlen((const char *)PLAINTEXT)); + assert_true(strncmp((const char *)buffer, (const char *)PLAINTEXT, len) == 0); + free(buffer); +} + +static void test_crypt_nosalt(void **state) +{ + (void)state; + + unsigned char KEY[] = "E5E9FA1BA31ECD1AE84F75CAAA474F3A663F05F412028F81DA65D26EE56424B2"; + unsigned char IV[] = "E93DA465B309C53FEC5FF93C9637DA58"; + unsigned char CRYPTTEXT[] = "E4B7745CA14039555CECD548BB33E0C3"; + unsigned char PLAINTEXT[] = "CRYPTTEST"; + + struct cryptdata crypt; + hex2bin((crypt.key = calloc(1, strlen((const char *)KEY))), KEY); + hex2bin((crypt.iv = calloc(1, strlen((const char *)IV))), IV); + crypt.salt = NULL; + hex2bin((crypt.crypttext = calloc(1, strlen((const char *)CRYPTTEXT))), CRYPTTEXT); + + do_crypt(&crypt, &CRYPTTEXT[0], &PLAINTEXT[0]); + + free(crypt.key); + free(crypt.iv); + free(crypt.crypttext); +} + +static void test_crypt_salt(void **state) +{ + (void)state; + + unsigned char KEY[] = "69D54287F856D30B51B812FDF714556778CF31E1B104D9C68BD90C669C37D1AB"; + unsigned char IV[] = "E7039ABFCA63EB8EB1D320F7918275B2"; + unsigned char SALT[] = "F75A9C11F7F63C08"; + unsigned char CRYPTTEXT[] = "A17EBBB1A28459352FE3A994404E35AA"; + unsigned char PLAINTEXT[] = "CRYPTTEST"; + + struct cryptdata crypt; + hex2bin((crypt.key = calloc(1, strlen((const char *)KEY))), KEY); + hex2bin((crypt.iv = calloc(1, strlen((const char *)IV))), IV); + hex2bin((crypt.salt = calloc(1, strlen((const char *)SALT))), SALT); + hex2bin((crypt.crypttext = calloc(1, strlen((const char *)CRYPTTEXT))), CRYPTTEXT); + + do_crypt(&crypt, &CRYPTTEXT[0], &PLAINTEXT[0]); + + free(crypt.key); + free(crypt.iv); + free(crypt.salt); + free(crypt.crypttext); +} + +static void test_crypt_failure(void **state) +{ + (void)state; + + unsigned char KEY[] = "E5E9FA1BA31ECD1AE84F75CAAA474F3A663F05F412028F81DA65D26EE56424B2"; + unsigned char IV[] = "E93DA465B309C53FEC5FF93C9637DA58"; + unsigned char CRYPTTEXT[] = "CAFECAFECAFECAFECAFECAFECAFECAFE"; + + struct cryptdata crypt; + hex2bin((crypt.key = calloc(1, strlen((const char *)KEY))), KEY); + hex2bin((crypt.iv = calloc(1, strlen((const char *)IV))), IV); + crypt.salt = NULL; + hex2bin((crypt.crypttext = calloc(1, strlen((const char *)CRYPTTEXT))), CRYPTTEXT); + + int len; + void *dcrypt = swupdate_DECRYPT_init(crypt.key, crypt.iv, crypt.salt); + assert_non_null(dcrypt); + + unsigned char *buffer = calloc(1, strlen((const char *)CRYPTTEXT) + EVP_MAX_BLOCK_LENGTH); + int ret = swupdate_DECRYPT_update(dcrypt, buffer, &len, crypt.crypttext, strlen((const char *)CRYPTTEXT) / 2); + ret = swupdate_DECRYPT_final(dcrypt, crypt.crypttext, &len); + assert_true(ret != 0); + free(buffer); + + free(crypt.key); + free(crypt.iv); + free(crypt.salt); + free(crypt.crypttext); +} + +int main(void) +{ + int error_count = 0; + const struct CMUnitTest crypt_tests[] = { + cmocka_unit_test(test_crypt_nosalt), + cmocka_unit_test(test_crypt_failure), + cmocka_unit_test(test_crypt_salt) + }; + error_count += cmocka_run_group_tests_name("crypt", crypt_tests, NULL, NULL); + return error_count; +}
Signed-off-by: Christian Storm <christian.storm@siemens.com> --- Makefile | 7 ++- corelib/test/Makefile | 64 ++++++++++++++++++++ corelib/test/test_crypt.c | 148 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 218 insertions(+), 1 deletion(-) create mode 100644 corelib/test/Makefile create mode 100644 corelib/test/test_crypt.c