Skip to contentSkip to conversation

lib/crypto: sha1: Explicitly specify alignment of sha1_ctx::buf

PATCH In review Eric Biggers 1 participant 2 messages Mar 20 – Mar 21 Crypto API

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 lib/crypto: sha1: Explicitly specify alignment of sha1_ctx::buf

__sha1_final() writes a __be64 to &ctx->buf[56] using a plain write. That assumes that the alignment of buf is at least that of __be64. It is, since it immediately follows a u64 field. However, to make this assumption explicit it's best to specify the field alignment explicitly too, like what is done in the corresponding SHA-2 and MD5 structs.

---
 include/crypto/sha1.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
include/crypto/sha1.h +1 -1
index 4d973e016cd6..560ed4fd1703 100644
@@ -38,11 +38,11 @@ struct sha1_block_state {
  * @buf: partial block buffer; bytecount % SHA1_BLOCK_SIZE bytes are valid
  */
 struct sha1_ctx {
 	struct sha1_block_state state;
 	u64 bytecount;
-	u8 buf[SHA1_BLOCK_SIZE];
+	u8 buf[SHA1_BLOCK_SIZE] __aligned(__alignof__(__be64));
 };
 
 /**
  * sha1_init() - Initialize a SHA-1 context for a new message
  * @ctx: the context to initialize

base-commit: 6bc9effb4cbf9b6eba0f51aba1c8893dfd4c8100

Signature · 1 line
2.53.0
#1 lore raw
Quoted 16 lines · Eric Biggers

__sha1_final() writes a __be64 to &ctx->buf[56] using a plain write. That assumes that the alignment of buf is at least that of __be64. It is, since it immediately follows a u64 field. However, to make this assumption explicit it's best to specify the field alignment explicitly too, like what is done in the corresponding SHA-2 and MD5 structs.

---
 include/crypto/sha1.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
include/crypto/sha1.h +0 -0
index 4d973e016cd6..560ed4fd1703 100644

include/crypto/sha1.h struct sha1_block_state { · line 44

Quoted 8 lines
include/crypto/sha1.h +1 -1
@@ -38,11 +38,11 @@ struct sha1_block_state {
  * @buf: partial block buffer; bytecount % SHA1_BLOCK_SIZE bytes are valid
  */
 struct sha1_ctx {
 	struct sha1_block_state state;
 	u64 bytecount;
-	u8 buf[SHA1_BLOCK_SIZE];
+	u8 buf[SHA1_BLOCK_SIZE] __aligned(__alignof__(__be64));
 };

Surprisingly, this patch actually breaks the build on 32-bit x86. The static assertions in crypto/sha1.c that verify the consistency of 'struct sha1_ctx' and 'struct sha1_state' start failing. gcc puts bytecount and buf at offsets 20 and 28 in the struct. I.e., it puts the u64 field on only a 4-byte boundary. However, __alignof__(__be64) actually returns 8, causing the offset of buf to change from 28 to 32. (The result is the same if __alignof__(u64) is used instead.)

Apparently __alignof__ returns the "preferred alignment". But what we want is "minimum alignment". Which is C11's _Alignof, which was deprecated in C23 and replaced with "alignof". Sigh.

Probably best to just keep this as-is until we can get drivers/crypto/ migrated off of 'struct sha1_state' and remove that.

- Eric