1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3 * SHA-1 message digest algorithm
4 *
5 * Copyright 2025 Google LLC
6 */
7 #include <linux/bitops.h>
8 #include <linux/kernel.h>
9 #include <linux/unaligned.h>
10 #include <string.h>
11
12 #include "sha1.h"
13
14 #define SHA1_BLOCK_SIZE 64
15
16 static const u32 sha1_K[4] = { 0x5A827999, 0x6ED9EBA1, 0x8F1BBCDC, 0xCA62C1D6 };
17
18 #define SHA1_ROUND(i, a, b, c, d, e) \
19 do { \
20 if ((i) >= 16) \
21 w[i] = rol32(w[(i) - 16] ^ w[(i) - 14] ^ w[(i) - 8] ^ \
22 w[(i) - 3], \
23 1); \
24 e += w[i] + rol32(a, 5) + sha1_K[(i) / 20]; \
25 if ((i) < 20) \
26 e += (b & (c ^ d)) ^ d; \
27 else if ((i) < 40 || (i) >= 60) \
28 e += b ^ c ^ d; \
29 else \
30 e += (c & d) ^ (b & (c ^ d)); \
31 b = rol32(b, 30); \
32 /* The new (a, b, c, d, e) is the old (e, a, b, c, d). */ \
33 } while (0)
34
35 #define SHA1_5ROUNDS(i) \
36 do { \
37 SHA1_ROUND((i) + 0, a, b, c, d, e); \
38 SHA1_ROUND((i) + 1, e, a, b, c, d); \
39 SHA1_ROUND((i) + 2, d, e, a, b, c); \
40 SHA1_ROUND((i) + 3, c, d, e, a, b); \
41 SHA1_ROUND((i) + 4, b, c, d, e, a); \
42 } while (0)
43
44 #define SHA1_20ROUNDS(i) \
45 do { \
46 SHA1_5ROUNDS((i) + 0); \
47 SHA1_5ROUNDS((i) + 5); \
48 SHA1_5ROUNDS((i) + 10); \
49 SHA1_5ROUNDS((i) + 15); \
50 } while (0)
51
sha1_blocks(u32 h[5],const u8 * data,size_t nblocks)52 static void sha1_blocks(u32 h[5], const u8 *data, size_t nblocks)
53 {
54 while (nblocks--) {
55 u32 a = h[0];
56 u32 b = h[1];
57 u32 c = h[2];
58 u32 d = h[3];
59 u32 e = h[4];
60 u32 w[80];
61
62 for (int i = 0; i < 16; i++)
63 w[i] = get_unaligned_be32(&data[i * 4]);
64 SHA1_20ROUNDS(0);
65 SHA1_20ROUNDS(20);
66 SHA1_20ROUNDS(40);
67 SHA1_20ROUNDS(60);
68
69 h[0] += a;
70 h[1] += b;
71 h[2] += c;
72 h[3] += d;
73 h[4] += e;
74 data += SHA1_BLOCK_SIZE;
75 }
76 }
77
78 /* Calculate the SHA-1 message digest of the given data. */
sha1(const void * data,size_t len,u8 out[SHA1_DIGEST_SIZE])79 void sha1(const void *data, size_t len, u8 out[SHA1_DIGEST_SIZE])
80 {
81 u32 h[5] = { 0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476,
82 0xC3D2E1F0 };
83 u8 final_data[2 * SHA1_BLOCK_SIZE] = { 0 };
84 size_t final_len = len % SHA1_BLOCK_SIZE;
85
86 sha1_blocks(h, data, len / SHA1_BLOCK_SIZE);
87
88 memcpy(final_data, data + len - final_len, final_len);
89 final_data[final_len] = 0x80;
90 final_len = round_up(final_len + 9, SHA1_BLOCK_SIZE);
91 put_unaligned_be64((u64)len * 8, &final_data[final_len - 8]);
92
93 sha1_blocks(h, final_data, final_len / SHA1_BLOCK_SIZE);
94
95 for (int i = 0; i < 5; i++)
96 put_unaligned_be32(h[i], &out[i * 4]);
97 }
98