File Index
Files and directories
Sign in
FILE

sha1.c

File preview with syntax highlighting.

linux-6.19.14/tools/perf/util/sha1.c C
 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
16static 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
52static 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. */
79void 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}
~/ Read-only file preview.