Skip to content

Commit c00c554

Browse files
sha1sum.c, sha256.c: make code work with -fstrict-aliasing
-fstrict-aliasing is enabled by default when using optimization levels higher than 1, including -Os. With that option, compiler may assume that object of one type never resides at the same address as object of a different type. Both sha1_final() and sha256_final() used to write message length by casting a pointer to buffer into a pointer to u64, while surrounding code operated on the buffer directly. The problem manifests in GCC 11 and later versions. The commit fixes this issue and another UB caused by unaligned access at the beginning of transformation step by using memcpy() in both cases. Signed-off-by: Krystian Hebel <[email protected]> Signed-off-by: Sergii Dmytruk <[email protected]>
1 parent 87833a0 commit c00c554

File tree

2 files changed

+44
-39
lines changed

2 files changed

+44
-39
lines changed

sha1sum.c

Lines changed: 29 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -36,23 +36,18 @@ static inline u32 rol( u32 x, int n)
3636

3737
typedef struct {
3838
u32 count;
39-
union {
40-
struct {
41-
u32 h0, h1, h2, h3, h4;
42-
};
43-
u32 h[5];
44-
};
45-
unsigned char buf[64];
39+
u32 h[5];
40+
u8 buf[64];
4641
} SHA1_CONTEXT;
4742

4843
static void sha1_init( SHA1_CONTEXT *hd )
4944
{
5045
*hd = (SHA1_CONTEXT){
51-
.h0 = 0x67452301,
52-
.h1 = 0xefcdab89,
53-
.h2 = 0x98badcfe,
54-
.h3 = 0x10325476,
55-
.h4 = 0xc3d2e1f0,
46+
.h[0] = 0x67452301,
47+
.h[1] = 0xefcdab89,
48+
.h[2] = 0x98badcfe,
49+
.h[3] = 0x10325476,
50+
.h[4] = 0xc3d2e1f0,
5651
};
5752
}
5853

@@ -70,20 +65,24 @@ static u32 sha1_blend(u32 *x, unsigned int i)
7065
*/
7166
static void sha1_transform(SHA1_CONTEXT *hd, const void *_data)
7267
{
73-
const u32 *data = _data;
68+
const u8 *data = _data;
7469
u32 a,b,c,d,e;
7570
u32 x[16];
7671
int i;
7772

7873
/* get values from the chaining vars */
79-
a = hd->h0;
80-
b = hd->h1;
81-
c = hd->h2;
82-
d = hd->h3;
83-
e = hd->h4;
74+
a = hd->h[0];
75+
b = hd->h[1];
76+
c = hd->h[2];
77+
d = hd->h[3];
78+
e = hd->h[4];
8479

8580
for ( i = 0; i < 16; ++i )
86-
x[i] = cpu_to_be32(data[i]);
81+
{
82+
u32 tmp;
83+
memcpy(&tmp, &data[i*sizeof(u32)], sizeof(u32));
84+
x[i] = be32_to_cpu(tmp);
85+
}
8786

8887

8988
#define K1 0x5A827999L
@@ -147,11 +146,11 @@ static void sha1_transform(SHA1_CONTEXT *hd, const void *_data)
147146
}
148147

149148
/* Update chaining vars */
150-
hd->h0 += a;
151-
hd->h1 += b;
152-
hd->h2 += c;
153-
hd->h3 += d;
154-
hd->h4 += e;
149+
hd->h[0] += a;
150+
hd->h[1] += b;
151+
hd->h[2] += c;
152+
hd->h[3] += d;
153+
hd->h[4] += e;
155154
}
156155

157156

@@ -176,6 +175,7 @@ static void
176175
sha1_final(SHA1_CONTEXT *hd, u8 hash[SHA1_DIGEST_SIZE])
177176
{
178177
unsigned int partial = hd->count & 0x3f;
178+
u64 ml = cpu_to_be64((u64)hd->count << 3);
179179

180180
/* Start padding */
181181
hd->buf[partial++] = 0x80;
@@ -191,13 +191,14 @@ sha1_final(SHA1_CONTEXT *hd, u8 hash[SHA1_DIGEST_SIZE])
191191
memset(hd->buf + partial, 0, 56 - partial);
192192

193193
/* append the 64 bit count */
194-
u64 *count = (void *)&hd->buf[56];
195-
*count = cpu_to_be64((u64)hd->count << 3);
194+
memcpy(hd->buf + 56, &ml, sizeof(ml));
196195
sha1_transform(hd, hd->buf);
197196

198-
u32 *p = (void *)hash;
199197
for ( int i = 0; i < 5; ++i )
200-
p[i] = be32_to_cpu(hd->h[i]);
198+
{
199+
u32 be = cpu_to_be32(hd->h[i]);
200+
memcpy(&hash[i*sizeof(u32)], &be, sizeof(u32));
201+
}
201202
}
202203

203204
void sha1sum(u8 hash[static SHA1_DIGEST_SIZE], const void *ptr, u32 len)

sha256.c

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,10 @@
2020
#include <sha256.h>
2121
#include <string.h>
2222

23-
#define SHA256_BLOCK_SIZE 64
24-
2523
struct sha256_state {
2624
u32 state[SHA256_DIGEST_SIZE / 4];
2725
u32 count;
28-
u8 buf[SHA256_BLOCK_SIZE];
26+
u8 buf[64];
2927
};
3028

3129
static inline u32 ror32(u32 word, unsigned int shift)
@@ -78,14 +76,18 @@ static const u32 K[] = {
7876

7977
static void sha256_transform(u32 *state, const void *_input)
8078
{
81-
const u32 *input = _input;
79+
const u8 *input = _input;
8280
u32 a, b, c, d, e, f, g, h, t1, t2;
8381
u32 W[16];
8482
int i;
8583

8684
/* load the input */
8785
for ( i = 0; i < 16; i++ )
88-
W[i] = be32_to_cpu(input[i]);
86+
{
87+
u32 tmp;
88+
memcpy(&tmp, &input[i*sizeof(u32)], sizeof(u32));
89+
W[i] = be32_to_cpu(tmp);
90+
}
8991

9092
/* load the state into our registers */
9193
a = state[0]; b = state[1]; c = state[2]; d = state[3];
@@ -163,31 +165,33 @@ static void sha256_once(struct sha256_state *sctx, const void *data, u32 len)
163165

164166
static void sha256_final(struct sha256_state *sctx, void *_dst)
165167
{
166-
u32 *dst = _dst;
167-
u64 *count;
168+
u8 *dst = _dst;
168169
unsigned int i, partial = sctx->count & 0x3f;
170+
u64 ml = cpu_to_be64((u64)sctx->count << 3);
169171

170172
/* Start padding */
171173
sctx->buf[partial++] = 0x80;
172174

173175
if ( partial > 56 )
174176
{
175177
/* Need one extra block - pad to 64 */
176-
memset(sctx->buf + partial, 0, 64 - partial);
178+
memset(sctx->buf + partial, 0, sizeof(sctx->buf) - partial);
177179
sha256_transform(sctx->state, sctx->buf);
178180
partial = 0;
179181
}
180182
/* Pad to 56 */
181183
memset(sctx->buf + partial, 0, 56 - partial);
182184

183185
/* Append the 64 bit count */
184-
count = (void *)&sctx->buf[56];
185-
*count = cpu_to_be64((u64)sctx->count << 3);
186+
memcpy(sctx->buf + 56, &ml, sizeof(ml));
186187
sha256_transform(sctx->state, sctx->buf);
187188

188189
/* Store state in digest */
189190
for ( i = 0; i < 8; i++ )
190-
dst[i] = cpu_to_be32(sctx->state[i]);
191+
{
192+
u32 be = cpu_to_be32(sctx->state[i]);
193+
memcpy(&dst[i*sizeof(u32)], &be, sizeof(u32));
194+
}
191195
}
192196

193197
void sha256sum(u8 hash[static SHA256_DIGEST_SIZE], const void *data, u32 len)

0 commit comments

Comments
 (0)