diff --git a/src/fundamental/sha256.c b/src/fundamental/sha256.c
index 6fcb37a7d9e..67d83b5f1cd 100644
--- a/src/fundamental/sha256.c
+++ b/src/fundamental/sha256.c
@@ -49,6 +49,20 @@
# define SWAP64(n) (n)
#endif
+/* The condition below is from glibc's string/string-inline.c.
+ * See definition of _STRING_INLINE_unaligned. */
+#if !defined(__mc68020__) && !defined(__s390__) && !defined(__i386__)
+
+/* To check alignment gcc has an appropriate operator. Other compilers don't. */
+# if __GNUC__ >= 2
+# define UNALIGNED_P(p) (((size_t) p) % __alignof__(uint32_t) != 0)
+# else
+# define UNALIGNED_P(p) (((size_t) p) % sizeof(uint32_t) != 0)
+# endif
+#else
+# define UNALIGNED_P(p) false
+#endif
+
/* This array contains the bytes used to pad the buffer to the next
64-byte boundary. (FIPS 180-2:5.1.1) */
static const uint8_t fillbuf[64] = {
@@ -96,10 +110,7 @@ void sha256_init_ctx(struct sha256_ctx *ctx) {
}
/* Process the remaining bytes in the internal buffer and the usual
- prolog according to the standard and write the result to RESBUF.
-
- IMPORTANT: On some systems it is required that RESBUF is correctly
- aligned for a 32 bits value. */
+ prolog according to the standard and write the result to RESBUF. */
void *sha256_finish_ctx(struct sha256_ctx *ctx, void *resbuf) {
/* Take yet unprocessed bytes into account. */
uint32_t bytes = ctx->buflen;
@@ -124,7 +135,10 @@ void *sha256_finish_ctx(struct sha256_ctx *ctx, void *resbuf) {
/* Put result from CTX in first 32 bytes following RESBUF. */
for (size_t i = 0; i < 8; ++i)
- ((uint32_t *) resbuf)[i] = SWAP(ctx->H[i]);
+ if (UNALIGNED_P(resbuf))
+ memcpy((uint8_t*) resbuf + i * sizeof(uint32_t), (uint32_t[]) { SWAP(ctx->H[i]) }, sizeof(uint32_t));
+ else
+ ((uint32_t *) resbuf)[i] = SWAP(ctx->H[i]);
return resbuf;
}
@@ -158,17 +172,6 @@ void sha256_process_bytes(const void *buffer, size_t len, struct sha256_ctx *ctx
/* Process available complete blocks. */
if (len >= 64) {
-
-/* The condition below is from glibc's string/string-inline.c.
- * See definition of _STRING_INLINE_unaligned. */
-#if !defined(__mc68020__) && !defined(__s390__) && !defined(__i386__)
-
-/* To check alignment gcc has an appropriate operator. Other compilers don't. */
-# if __GNUC__ >= 2
-# define UNALIGNED_P(p) (((size_t) p) % __alignof__(uint32_t) != 0)
-# else
-# define UNALIGNED_P(p) (((size_t) p) % sizeof(uint32_t) != 0)
-# endif
if (UNALIGNED_P(buffer))
while (len > 64) {
memcpy(ctx->buffer, buffer, 64);
@@ -176,9 +179,7 @@ void sha256_process_bytes(const void *buffer, size_t len, struct sha256_ctx *ctx
buffer = (const char *) buffer + 64;
len -= 64;
}
- else
-#endif
- {
+ else {
sha256_process_block(buffer, len & ~63, ctx);
buffer = (const char *) buffer + (len & ~63);
len &= 63;
diff --git a/src/test/meson.build b/src/test/meson.build
index d2bdd201ee3..cc590f4f3d9 100644
--- a/src/test/meson.build
+++ b/src/test/meson.build
@@ -670,6 +670,8 @@ tests += [
[], [], [], 'ENABLE_NSCD', 'manual'],
[files('test-hmac.c')],
+
+ [files('test-sha256.c')],
]
############################################################
diff --git a/src/test/test-hmac.c b/src/test/test-hmac.c
index 523f09495cd..1b788b191c0 100644
--- a/src/test/test-hmac.c
+++ b/src/test/test-hmac.c
@@ -10,59 +10,59 @@ static void hmac_sha256_by_string(const char *key, const char *value, uint8_t re
}
TEST(hmac) {
- uint8_t result[SHA256_DIGEST_SIZE];
- char *hex_result = NULL;
+ uint8_t result[SHA256_DIGEST_SIZE];
+ char *hex_result = NULL;
- /* Results compared with output of 'echo -n "" | openssl dgst -sha256 -hmac ""' */
+ /* Results compared with output of 'echo -n "" | openssl dgst -sha256 -hmac ""' */
- hmac_sha256_by_string("waldo",
- "",
- result);
- hex_result = hexmem(result, sizeof(result));
- assert_se(streq_ptr(hex_result, "cadd5e42114351181f3abff477641d88efb57d2b5641a1e5c6d623363a6d3bad"));
- hex_result = mfree(hex_result);
+ hmac_sha256_by_string("waldo",
+ "",
+ result);
+ hex_result = hexmem(result, sizeof(result));
+ assert_se(streq_ptr(hex_result, "cadd5e42114351181f3abff477641d88efb57d2b5641a1e5c6d623363a6d3bad"));
+ hex_result = mfree(hex_result);
- hmac_sha256_by_string("waldo",
- "baldohaldo",
- result);
- hex_result = hexmem(result, sizeof(result));
- assert_se(streq_ptr(hex_result, "c47ad5031ba21605e52c6ca68090d66a2dd5ccf84efa4bace15361a8cba63cda"));
- hex_result = mfree(hex_result);
+ hmac_sha256_by_string("waldo",
+ "baldohaldo",
+ result);
+ hex_result = hexmem(result, sizeof(result));
+ assert_se(streq_ptr(hex_result, "c47ad5031ba21605e52c6ca68090d66a2dd5ccf84efa4bace15361a8cba63cda"));
+ hex_result = mfree(hex_result);
- hmac_sha256_by_string("waldo",
- "baldo haldo",
- result);
- hex_result = hexmem(result, sizeof(result));
- assert_se(streq_ptr(hex_result, "4e8974ad6c08b98cc2519cd1e27aa7195769fcf86db1dd7ceaab4d44c490ad69"));
- hex_result = mfree(hex_result);
+ hmac_sha256_by_string("waldo",
+ "baldo haldo",
+ result);
+ hex_result = hexmem(result, sizeof(result));
+ assert_se(streq_ptr(hex_result, "4e8974ad6c08b98cc2519cd1e27aa7195769fcf86db1dd7ceaab4d44c490ad69"));
+ hex_result = mfree(hex_result);
- hmac_sha256_by_string("waldo",
- "baldo 4e8974ad6c08b98cc2519cd1e27aa7195769fcf86db1dd7ceaab4d44c490ad69 haldo",
- result);
- hex_result = hexmem(result, sizeof(result));
- assert_se(streq_ptr(hex_result, "039f3df430b19753ffb493e5b90708f75c5210b63c6bcbef3374eb3f0a3f97f7"));
- hex_result = mfree(hex_result);
+ hmac_sha256_by_string("waldo",
+ "baldo 4e8974ad6c08b98cc2519cd1e27aa7195769fcf86db1dd7ceaab4d44c490ad69 haldo",
+ result);
+ hex_result = hexmem(result, sizeof(result));
+ assert_se(streq_ptr(hex_result, "039f3df430b19753ffb493e5b90708f75c5210b63c6bcbef3374eb3f0a3f97f7"));
+ hex_result = mfree(hex_result);
- hmac_sha256_by_string("4e8974ad6c08b98cc2519cd1e27aa7195769fcf86db1dd7ceaab4d44c490ad69",
- "baldo haldo",
- result);
- hex_result = hexmem(result, sizeof(result));
- assert_se(streq_ptr(hex_result, "c4cfaf48077cbb0bbd177a09e59ec4c248f4ca771503410f5b54b98d88d2f47b"));
- hex_result = mfree(hex_result);
+ hmac_sha256_by_string("4e8974ad6c08b98cc2519cd1e27aa7195769fcf86db1dd7ceaab4d44c490ad69",
+ "baldo haldo",
+ result);
+ hex_result = hexmem(result, sizeof(result));
+ assert_se(streq_ptr(hex_result, "c4cfaf48077cbb0bbd177a09e59ec4c248f4ca771503410f5b54b98d88d2f47b"));
+ hex_result = mfree(hex_result);
- hmac_sha256_by_string("4e8974ad6c08b98cc2519cd1e27aa7195769fcf86db1dd7ceaab4d44c490ad69",
- "supercalifragilisticexpialidocious",
- result);
- hex_result = hexmem(result, sizeof(result));
- assert_se(streq_ptr(hex_result, "2c059e7a63c4c3b23f47966a65fd2f8a2f5d7161e2e90d78ff68866b5c375cb7"));
- hex_result = mfree(hex_result);
+ hmac_sha256_by_string("4e8974ad6c08b98cc2519cd1e27aa7195769fcf86db1dd7ceaab4d44c490ad69",
+ "supercalifragilisticexpialidocious",
+ result);
+ hex_result = hexmem(result, sizeof(result));
+ assert_se(streq_ptr(hex_result, "2c059e7a63c4c3b23f47966a65fd2f8a2f5d7161e2e90d78ff68866b5c375cb7"));
+ hex_result = mfree(hex_result);
- hmac_sha256_by_string("4e8974ad6c08b98cc2519cd1e27aa7195769fcf86db1dd7ceaab4d44c490ad69c47ad5031ba21605e52c6ca68090d66a2dd5ccf84efa4bace15361a8cba63cda",
- "supercalifragilisticexpialidocious",
- result);
- hex_result = hexmem(result, sizeof(result));
- assert_se(streq_ptr(hex_result, "1dd1d1d45b9d9f9673dc9983c968c46ff3168e03cfeb4156a219eba1af4cff5f"));
- hex_result = mfree(hex_result);
+ hmac_sha256_by_string("4e8974ad6c08b98cc2519cd1e27aa7195769fcf86db1dd7ceaab4d44c490ad69c47ad5031ba21605e52c6ca68090d66a2dd5ccf84efa4bace15361a8cba63cda",
+ "supercalifragilisticexpialidocious",
+ result);
+ hex_result = hexmem(result, sizeof(result));
+ assert_se(streq_ptr(hex_result, "1dd1d1d45b9d9f9673dc9983c968c46ff3168e03cfeb4156a219eba1af4cff5f"));
+ hex_result = mfree(hex_result);
}
DEFINE_TEST_MAIN(LOG_INFO);
diff --git a/src/test/test-sha256.c b/src/test/test-sha256.c
new file mode 100644
index 00000000000..f168e4c355b
--- /dev/null
+++ b/src/test/test-sha256.c
@@ -0,0 +1,50 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+
+#include "hexdecoct.h"
+#include "sha256.h"
+#include "string-util.h"
+#include "tests.h"
+
+static void sha256_process_string(const char *key, struct sha256_ctx *ctx) {
+ sha256_process_bytes(key, strlen(key), ctx);
+}
+
+static void test_sha256_one(const char *key, const char *expect) {
+ uint8_t result[SHA256_DIGEST_SIZE + 3];
+ _cleanup_free_ char *str = NULL;
+ struct sha256_ctx ctx;
+
+ log_debug("\"%s\" → %s", key, expect);
+
+ assert_se(str = new(char, strlen(key) + 4));
+
+ /* This tests unaligned buffers. */
+
+ for (size_t i = 0; i < 4; i++) {
+ strcpy(str + i, key);
+
+ for (size_t j = 0; j < 4; j++) {
+ _cleanup_free_ char *hex_result = NULL;
+
+ sha256_init_ctx(&ctx);
+ sha256_process_string(str + i, &ctx);
+ sha256_finish_ctx(&ctx, result + j);
+
+ hex_result = hexmem(result + j, SHA256_DIGEST_SIZE);
+ assert_se(streq_ptr(hex_result, expect));
+ }
+ }
+}
+
+TEST(sha256) {
+ /* Results compared with output of 'echo -n "" | sha256sum -' */
+
+ test_sha256_one("abcdefghijklmnopqrstuvwxyz",
+ "71c480df93d6ae2f1efad1447c66c9525e316218cf51fc8d9ed832f2daf18b73");
+ test_sha256_one("ほげほげあっちょんぶりけ",
+ "ce7225683653be3b74861c5a4323b6baf3c3ceb361413ca99e3a5b52c04411bd");
+ test_sha256_one("0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789",
+ "9cfe7faff7054298ca87557e15a10262de8d3eee77827417fbdfea1c41b9ec23");
+}
+
+DEFINE_TEST_MAIN(LOG_INFO);