Botan 3.8.1
Crypto and TLS for C&
sha1_x86.cpp
Go to the documentation of this file.
1/*
2* Based on public domain code by Sean Gulley
3*
4* Adapted to Botan by Jeffrey Walton.
5*
6* Further changes
7*
8* (C) 2017,2025 Jack Lloyd
9*
10* Botan is released under the Simplified BSD License (see license.txt)
11*/
12
13#include <botan/internal/sha1.h>
14
15#include <botan/internal/isa_extn.h>
16#include <botan/internal/simd_4x32.h>
17#include <immintrin.h>
18
19namespace Botan {
20
21namespace {
22
23BOTAN_FORCE_INLINE BOTAN_FN_ISA_SHANI SIMD_4x32 sha1_x86_nexte(const SIMD_4x32& x, const SIMD_4x32& y) {
24 return SIMD_4x32(_mm_sha1nexte_epu32(x.raw(), y.raw()));
25}
26
27BOTAN_FORCE_INLINE BOTAN_FN_ISA_SHANI SIMD_4x32 sha1_x86_msg1(const SIMD_4x32& W0, const SIMD_4x32& W1) {
28 return SIMD_4x32(_mm_sha1msg1_epu32(W0.raw(), W1.raw()));
29}
30
31BOTAN_FORCE_INLINE BOTAN_FN_ISA_SHANI void sha1_x86_next_msg(const SIMD_4x32& W0,
32 SIMD_4x32& W1,
33 SIMD_4x32& W2,
34 SIMD_4x32& W3) {
35 W3 = SIMD_4x32(_mm_sha1msg1_epu32(W3.raw(), W0.raw()));
36 W1 = SIMD_4x32(_mm_sha1msg2_epu32(W1.raw(), W0.raw()));
37 W2 ^= W0;
38}
39
40template <uint8_t R1, uint8_t R2 = R1>
41BOTAN_FORCE_INLINE BOTAN_FN_ISA_SHANI void sha1_x86_rnds8(SIMD_4x32& ABCD,
42 SIMD_4x32& E,
43 const SIMD_4x32& W0,
44 const SIMD_4x32& W1) {
45 auto TE = ABCD;
46 ABCD = SIMD_4x32(_mm_sha1rnds4_epu32(ABCD.raw(), sha1_x86_nexte(E, W0).raw(), R1));
47
48 E = ABCD;
49 ABCD = SIMD_4x32(_mm_sha1rnds4_epu32(ABCD.raw(), sha1_x86_nexte(TE, W1).raw(), R2));
50}
51
52BOTAN_FORCE_INLINE BOTAN_FN_ISA_SHANI SIMD_4x32 rev_words(const SIMD_4x32& v) {
53 return SIMD_4x32(_mm_shuffle_epi32(v.raw(), 0b00011011));
54}
55
56} // namespace
57
58void BOTAN_FN_ISA_SHANI SHA_1::sha1_compress_x86(digest_type& digest,
59 std::span<const uint8_t> input_span,
60 size_t blocks) {
61 const uint8_t* input = input_span.data();
62
63 SIMD_4x32 ABCD = rev_words(SIMD_4x32::load_le(&digest[0]));
64 SIMD_4x32 E0 = SIMD_4x32(0, 0, 0, digest[4]);
65
66 while(blocks > 0) {
67 // Save current hash
68 const auto ABCD_SAVE = ABCD;
69 const auto E0_SAVE = E0;
70
71 auto W0 = rev_words(SIMD_4x32::load_be(input));
72 auto W1 = rev_words(SIMD_4x32::load_be(input + 16));
73 auto W2 = rev_words(SIMD_4x32::load_be(input + 32));
74 auto W3 = rev_words(SIMD_4x32::load_be(input + 48));
75
76 auto E1 = ABCD;
77 ABCD = SIMD_4x32(_mm_sha1rnds4_epu32(ABCD.raw(), _mm_add_epi32(E0.raw(), W0.raw()), 0));
78
79 E0 = ABCD;
80 ABCD = SIMD_4x32(_mm_sha1rnds4_epu32(ABCD.raw(), _mm_sha1nexte_epu32(E1.raw(), W1.raw()), 0));
81
82 sha1_x86_rnds8<0>(ABCD, E0, W2, W3);
83
84 W0 = sha1_x86_msg1(W0, W1);
85 W1 = sha1_x86_msg1(W1, W2);
86 W0 ^= W2;
87
88 sha1_x86_next_msg(W3, W0, W1, W2);
89 sha1_x86_next_msg(W0, W1, W2, W3);
90 sha1_x86_rnds8<0, 1>(ABCD, E0, W0, W1);
91
92 sha1_x86_next_msg(W1, W2, W3, W0);
93 sha1_x86_next_msg(W2, W3, W0, W1);
94 sha1_x86_rnds8<1>(ABCD, E0, W2, W3);
95
96 sha1_x86_next_msg(W3, W0, W1, W2);
97 sha1_x86_next_msg(W0, W1, W2, W3);
98 sha1_x86_rnds8<1>(ABCD, E0, W0, W1);
99
100 sha1_x86_next_msg(W1, W2, W3, W0);
101 sha1_x86_next_msg(W2, W3, W0, W1);
102 sha1_x86_rnds8<2>(ABCD, E0, W2, W3);
103
104 sha1_x86_next_msg(W3, W0, W1, W2);
105 sha1_x86_next_msg(W0, W1, W2, W3);
106 sha1_x86_rnds8<2>(ABCD, E0, W0, W1);
107
108 sha1_x86_next_msg(W1, W2, W3, W0);
109 sha1_x86_next_msg(W2, W3, W0, W1);
110 sha1_x86_rnds8<2, 3>(ABCD, E0, W2, W3);
111
112 sha1_x86_next_msg(W3, W0, W1, W2);
113 sha1_x86_next_msg(W0, W1, W2, W3);
114 sha1_x86_rnds8<3>(ABCD, E0, W0, W1);
115
116 sha1_x86_next_msg(W1, W2, W3, W0);
117 sha1_x86_next_msg(W2, W3, W0, W1);
118 sha1_x86_rnds8<3>(ABCD, E0, W2, W3);
119
120 ABCD += ABCD_SAVE;
121 E0 = sha1_x86_nexte(E0, E0_SAVE);
122
123 input += 64;
124 blocks--;
125 }
126
127 rev_words(ABCD).store_le(&digest[0]);
128 digest[4] = _mm_extract_epi32(E0.raw(), 3);
129}
130
131} // namespace Botan
static void sha1_compress_x86(digest_type &digest, std::span< const uint8_t > blocks, size_t block_count)
Definition sha1_x86.cpp:58
secure_vector< uint32_t > digest_type
Definition sha1.h:20
static SIMD_4x32 BOTAN_FN_ISA_SIMD_4X32 load_be(const void *in) noexcept
Definition simd_4x32.h:166
native_simd_type raw() const noexcept
Definition simd_4x32.h:754
static SIMD_4x32 load_le(const void *in) noexcept
Definition simd_4x32.h:143
#define BOTAN_FORCE_INLINE
Definition compiler.h:85