]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
sha256: use memcpy() when result buffer is unaligned
authorYu Watanabe <watanabe.yu+github@gmail.com>
Tue, 31 May 2022 17:31:10 +0000 (02:31 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Thu, 2 Jun 2022 05:14:22 +0000 (14:14 +0900)
Fixes #23578.

src/fundamental/sha256.c

index 6fcb37a7d9e2ae5ff5fa70b004598ce54cc7f857..67d83b5f1cd64957ebd46aa39c1e9ec7ab144db8 100644 (file)
 # 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;