Merge pull request #25667 from poettering/sha256-align-fix
sha256 alignment fixes/rework
This commit is contained in:
+2
-18
@@ -4,6 +4,8 @@
|
||||
#include <endian.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "unaligned-fundamental.h"
|
||||
|
||||
/* BE */
|
||||
|
||||
static inline uint16_t unaligned_read_be16(const void *_u) {
|
||||
@@ -79,21 +81,3 @@ static inline void unaligned_write_le64(void *_u, uint64_t a) {
|
||||
|
||||
u->x = le64toh(a);
|
||||
}
|
||||
|
||||
#if __BYTE_ORDER == __BIG_ENDIAN
|
||||
#define unaligned_read_ne16 unaligned_read_be16
|
||||
#define unaligned_read_ne32 unaligned_read_be32
|
||||
#define unaligned_read_ne64 unaligned_read_be64
|
||||
|
||||
#define unaligned_write_ne16 unaligned_write_be16
|
||||
#define unaligned_write_ne32 unaligned_write_be32
|
||||
#define unaligned_write_ne64 unaligned_write_be64
|
||||
#else
|
||||
#define unaligned_read_ne16 unaligned_read_le16
|
||||
#define unaligned_read_ne32 unaligned_read_le32
|
||||
#define unaligned_read_ne64 unaligned_read_le64
|
||||
|
||||
#define unaligned_write_ne16 unaligned_write_le16
|
||||
#define unaligned_write_ne32 unaligned_write_le32
|
||||
#define unaligned_write_ne64 unaligned_write_le64
|
||||
#endif
|
||||
|
||||
@@ -327,14 +327,23 @@ static inline size_t ALIGN_TO(size_t l, size_t ali) {
|
||||
return ((l + ali - 1) & ~(ali - 1));
|
||||
}
|
||||
|
||||
#define ALIGN2(l) ALIGN_TO(l, 2)
|
||||
#define ALIGN4(l) ALIGN_TO(l, 4)
|
||||
#define ALIGN8(l) ALIGN_TO(l, 8)
|
||||
#define ALIGN2_PTR(p) ((void*) ALIGN2((uintptr_t) p))
|
||||
#define ALIGN4_PTR(p) ((void*) ALIGN4((uintptr_t) p))
|
||||
#define ALIGN8_PTR(p) ((void*) ALIGN8((uintptr_t) p))
|
||||
#ifndef SD_BOOT
|
||||
/* libefi also provides ALIGN, and we do not use them in sd-boot explicitly. */
|
||||
#define ALIGN(l) ALIGN_TO(l, sizeof(void*))
|
||||
#define ALIGN_PTR(p) ((void*) ALIGN((uintptr_t) (p)))
|
||||
#endif
|
||||
|
||||
/* Checks if the specified pointer is aligned as appropriate for the specific type */
|
||||
#define IS_ALIGNED16(p) (((uintptr_t) p) % __alignof__(uint16_t) == 0)
|
||||
#define IS_ALIGNED32(p) (((uintptr_t) p) % __alignof__(uint32_t) == 0)
|
||||
#define IS_ALIGNED64(p) (((uintptr_t) p) % __alignof__(uint64_t) == 0)
|
||||
|
||||
/* Same as ALIGN_TO but callable in constant contexts. */
|
||||
#define CONST_ALIGN_TO(l, ali) \
|
||||
__builtin_choose_expr( \
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
|
||||
#include "macro-fundamental.h"
|
||||
#include "sha256.h"
|
||||
#include "unaligned-fundamental.h"
|
||||
|
||||
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
|
||||
# define SWAP(n) \
|
||||
@@ -48,14 +49,6 @@
|
||||
# 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__)
|
||||
# define UNALIGNED_P(p) (((uintptr_t) p) % __alignof__(uint32_t) != 0)
|
||||
#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] = {
|
||||
@@ -128,11 +121,7 @@ uint8_t *sha256_finish_ctx(struct sha256_ctx *ctx, uint8_t resbuf[static SHA256_
|
||||
|
||||
/* Put result from CTX in first 32 bytes following RESBUF. */
|
||||
for (size_t i = 0; i < 8; ++i)
|
||||
if (UNALIGNED_P(resbuf))
|
||||
memcpy(resbuf + i * sizeof(uint32_t), (uint32_t[]) { SWAP(ctx->H[i]) }, sizeof(uint32_t));
|
||||
else
|
||||
((uint32_t *) resbuf)[i] = SWAP(ctx->H[i]);
|
||||
|
||||
unaligned_write_ne32(resbuf + i * sizeof(uint32_t), SWAP(ctx->H[i]));
|
||||
return resbuf;
|
||||
}
|
||||
|
||||
@@ -165,18 +154,17 @@ void sha256_process_bytes(const void *buffer, size_t len, struct sha256_ctx *ctx
|
||||
|
||||
/* Process available complete blocks. */
|
||||
if (len >= 64) {
|
||||
if (UNALIGNED_P(buffer))
|
||||
if (IS_ALIGNED32(buffer)) {
|
||||
sha256_process_block(buffer, len & ~63, ctx);
|
||||
buffer = (const char *) buffer + (len & ~63);
|
||||
len &= 63;
|
||||
} else
|
||||
while (len > 64) {
|
||||
memcpy(ctx->buffer, buffer, 64);
|
||||
sha256_process_block(ctx->buffer, 64, ctx);
|
||||
buffer = (const char *) buffer + 64;
|
||||
len -= 64;
|
||||
}
|
||||
else {
|
||||
sha256_process_block(buffer, len & ~63, ctx);
|
||||
buffer = (const char *) buffer + (len & ~63);
|
||||
len &= 63;
|
||||
}
|
||||
}
|
||||
|
||||
/* Move remaining bytes into internal buffer. */
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
#pragma once
|
||||
|
||||
#include "stdint.h"
|
||||
#include <stdint.h>
|
||||
|
||||
#define SHA256_DIGEST_SIZE 32
|
||||
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
static inline uint16_t unaligned_read_ne16(const void *_u) {
|
||||
const struct __attribute__((__packed__, __may_alias__)) { uint16_t x; } *u = _u;
|
||||
|
||||
return u->x;
|
||||
}
|
||||
|
||||
static inline uint32_t unaligned_read_ne32(const void *_u) {
|
||||
const struct __attribute__((__packed__, __may_alias__)) { uint32_t x; } *u = _u;
|
||||
|
||||
return u->x;
|
||||
}
|
||||
|
||||
static inline uint64_t unaligned_read_ne64(const void *_u) {
|
||||
const struct __attribute__((__packed__, __may_alias__)) { uint64_t x; } *u = _u;
|
||||
|
||||
return u->x;
|
||||
}
|
||||
|
||||
static inline void unaligned_write_ne16(void *_u, uint16_t a) {
|
||||
struct __attribute__((__packed__, __may_alias__)) { uint16_t x; } *u = _u;
|
||||
|
||||
u->x = a;
|
||||
}
|
||||
|
||||
static inline void unaligned_write_ne32(void *_u, uint32_t a) {
|
||||
struct __attribute__((__packed__, __may_alias__)) { uint32_t x; } *u = _u;
|
||||
|
||||
u->x = a;
|
||||
}
|
||||
|
||||
static inline void unaligned_write_ne64(void *_u, uint64_t a) {
|
||||
struct __attribute__((__packed__, __may_alias__)) { uint64_t x; } *u = _u;
|
||||
|
||||
u->x = a;
|
||||
}
|
||||
@@ -531,4 +531,57 @@ TEST(ISPOWEROF2) {
|
||||
assert_se(!ISPOWEROF2(u));
|
||||
}
|
||||
|
||||
TEST(ALIGNED) {
|
||||
assert_se(IS_ALIGNED16(NULL));
|
||||
assert_se(IS_ALIGNED32(NULL));
|
||||
assert_se(IS_ALIGNED64(NULL));
|
||||
|
||||
uint64_t u64;
|
||||
uint32_t u32;
|
||||
uint16_t u16;
|
||||
|
||||
assert_se(IS_ALIGNED16(&u16));
|
||||
assert_se(IS_ALIGNED16(&u32));
|
||||
assert_se(IS_ALIGNED16(&u64));
|
||||
assert_se(IS_ALIGNED32(&u32));
|
||||
assert_se(IS_ALIGNED32(&u64));
|
||||
assert_se(IS_ALIGNED64(&u64));
|
||||
|
||||
_align_(32) uint8_t ua256;
|
||||
_align_(8) uint8_t ua64;
|
||||
_align_(4) uint8_t ua32;
|
||||
_align_(2) uint8_t ua16;
|
||||
|
||||
assert_se(IS_ALIGNED16(&ua256));
|
||||
assert_se(IS_ALIGNED32(&ua256));
|
||||
assert_se(IS_ALIGNED64(&ua256));
|
||||
|
||||
assert_se(IS_ALIGNED16(&ua64));
|
||||
assert_se(IS_ALIGNED32(&ua64));
|
||||
assert_se(IS_ALIGNED64(&ua64));
|
||||
|
||||
assert_se(IS_ALIGNED16(&ua32));
|
||||
assert_se(IS_ALIGNED32(&ua32));
|
||||
|
||||
assert_se(IS_ALIGNED16(&ua16));
|
||||
|
||||
#ifdef __x86_64__
|
||||
/* Conditionalized on x86-64, since there we know for sure that all three types are aligned to
|
||||
* their size. Too lazy to figure it out for other archs */
|
||||
void *p = UINT_TO_PTR(1); /* definitely not aligned */
|
||||
assert_se(!IS_ALIGNED16(p));
|
||||
assert_se(!IS_ALIGNED32(p));
|
||||
assert_se(!IS_ALIGNED64(p));
|
||||
|
||||
assert_se(IS_ALIGNED16(ALIGN2_PTR(p)));
|
||||
assert_se(IS_ALIGNED32(ALIGN4_PTR(p)));
|
||||
assert_se(IS_ALIGNED64(ALIGN8_PTR(p)));
|
||||
|
||||
p = UINT_TO_PTR(-1); /* also definitely not aligned */
|
||||
assert_se(!IS_ALIGNED16(p));
|
||||
assert_se(!IS_ALIGNED32(p));
|
||||
assert_se(!IS_ALIGNED64(p));
|
||||
#endif
|
||||
}
|
||||
|
||||
DEFINE_TEST_MAIN(LOG_INFO);
|
||||
|
||||
Reference in New Issue
Block a user