diff mbox

[resent,2/2] crypt: add unit tests for crypt functions

Message ID 20170817141546.31426-2-christian.storm@siemens.com
State Accepted
Delegated to: Stefano Babic
Headers show

Commit Message

Storm, Christian Aug. 17, 2017, 2:15 p.m. UTC
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

Comments

Stefano Babic Aug. 21, 2017, 10:36 a.m. UTC | #1
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 mbox

Patch

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;
+}