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 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. */ 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