diff --git a/sys/crypto/helper.c b/sys/crypto/helper.c index 81accc8d2988021eeb9f8f9c64057ceb2df7905b..fcf92ab0314f9b847ee481045fbbbac5ce0e90a7 100644 --- a/sys/crypto/helper.c +++ b/sys/crypto/helper.c @@ -33,3 +33,12 @@ int crypto_equals(const uint8_t *a, const uint8_t *b, size_t len) return diff; } + +/* Compiler should not be allowed to optimize this */ +void crypto_secure_wipe(void *buf, size_t len) +{ + volatile uint8_t *vbuf = (uint8_t*)buf; + for (size_t i = 0; i < len; i++) { + vbuf[i] = 0; + } +} diff --git a/sys/include/crypto/helper.h b/sys/include/crypto/helper.h index db0dd42374abe090259584ba0a23e6056852da7b..569813c54713b6eee156c7365d9aac5cbcfd17f2 100644 --- a/sys/include/crypto/helper.h +++ b/sys/include/crypto/helper.h @@ -49,6 +49,21 @@ void crypto_block_inc_ctr(uint8_t block[16], int L); */ int crypto_equals(const uint8_t *a, const uint8_t *b, size_t len); +/** + * @brief Secure wipe function. + * + * This wipe function zeros the supplied buffer in a way that the compiler is + * not allowed to optimize. This can be used to erase secrets from memory. + * + * Note that this function on its own could be insufficient against (data + * remanence) attacks. It is outside the scope of this function to thoroughly + * shred the memory area. + * + * @param[in] buf buffer to wipe + * @param[in] len size of the buffer in bytes + */ +void crypto_secure_wipe(void *buf, size_t len); + #ifdef __cplusplus } #endif diff --git a/tests/unittests/tests-crypto/tests-crypto-helper.c b/tests/unittests/tests-crypto/tests-crypto-helper.c new file mode 100644 index 0000000000000000000000000000000000000000..c9cf8d781a811ee8fc52f98531aedcc05af6b011 --- /dev/null +++ b/tests/unittests/tests-crypto/tests-crypto-helper.c @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2018 Koen Zandberg + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +#include <string.h> + +#include "embUnit/embUnit.h" +#include "crypto/helper.h" + +#define VALUE 0xAA + +/* Secret to wipe */ +static uint8_t secret[20]; + +void test_crypto_wipe(void) +{ + memset(secret, VALUE, sizeof(secret)); + /* Wipe everything except the last byte */ + crypto_secure_wipe(secret, sizeof(secret) - 1); + for (size_t i = 0; i < (sizeof(secret) - 1); i++) { + TEST_ASSERT_EQUAL_INT(0, secret[i]); + } + /* Check last byte */ + TEST_ASSERT_EQUAL_INT(VALUE, secret[19]); +} + +Test *tests_crypto_helper_tests(void) +{ + EMB_UNIT_TESTFIXTURES(fixtures) { + new_TestFixture(test_crypto_wipe), + }; + EMB_UNIT_TESTCALLER(crypto_helper_tests, NULL, NULL, fixtures); + return (Test *) &crypto_helper_tests; +} diff --git a/tests/unittests/tests-crypto/tests-crypto.c b/tests/unittests/tests-crypto/tests-crypto.c index d1c1ce2aaf05dc6d2f9f941203a0e0caeb7cc50c..38910467b2af9bdb17ae1c2b679f9df0298fc955 100644 --- a/tests/unittests/tests-crypto/tests-crypto.c +++ b/tests/unittests/tests-crypto/tests-crypto.c @@ -11,6 +11,7 @@ void tests_crypto(void) { + TESTS_RUN(tests_crypto_helper_tests()); TESTS_RUN(tests_crypto_chacha_tests()); TESTS_RUN(tests_crypto_aes_tests()); TESTS_RUN(tests_crypto_cipher_tests()); diff --git a/tests/unittests/tests-crypto/tests-crypto.h b/tests/unittests/tests-crypto/tests-crypto.h index f8cac4578d61d8c14016724d575173ec8c2b7ddc..0c6c8ba953b5a5915a73bbbb488523a7f6af08b2 100644 --- a/tests/unittests/tests-crypto/tests-crypto.h +++ b/tests/unittests/tests-crypto/tests-crypto.h @@ -33,6 +33,12 @@ extern "C" { */ void tests_crypto(void); +/** + * @brief Generates tests for helper functions + * + * @return embUnit tests + */ +Test *tests_crypto_helper_tests(void); /** * @brief Generates tests for crypto/chacha.h *