Botan 3.10.0
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
23// NOLINTBEGIN(portability-simd-intrinsics)
24
25BOTAN_FORCE_INLINE BOTAN_FN_ISA_SHANI SIMD_4x32 sha1_x86_nexte(const SIMD_4x32& x, const SIMD_4x32& y) {
26 return SIMD_4x32(_mm_sha1nexte_epu32(x.raw(), y.raw()));
27}
28
29BOTAN_FORCE_INLINE BOTAN_FN_ISA_SHANI SIMD_4x32 sha1_x86_msg1(const SIMD_4x32& W0, const SIMD_4x32& W1) {
30 return SIMD_4x32(_mm_sha1msg1_epu32(W0.raw(), W1.raw()));
31}
32
33BOTAN_FORCE_INLINE BOTAN_FN_ISA_SHANI void sha1_x86_next_msg(const SIMD_4x32& W0,
34 SIMD_4x32& W1,
35 SIMD_4x32& W2,
36 SIMD_4x32& W3) {
37 W3 = SIMD_4x32(_mm_sha1msg1_epu32(W3.raw(), W0.raw()));
38 W1 = SIMD_4x32(_mm_sha1msg2_epu32(W1.raw(), W0.raw()));
39 W2 ^= W0;
40}
41
42template <uint8_t R1, uint8_t R2 = R1>
43BOTAN_FORCE_INLINE BOTAN_FN_ISA_SHANI void sha1_x86_first8(SIMD_4x32& ABCD,
44 SIMD_4x32& E,
45 const SIMD_4x32& W0,
46 const SIMD_4x32& W1) {
47 auto TE = ABCD;
48 ABCD = SIMD_4x32(_mm_sha1rnds4_epu32(ABCD.raw(), (E + W0).raw(), R1));
49
50 E = ABCD;
51 ABCD = SIMD_4x32(_mm_sha1rnds4_epu32(ABCD.raw(), sha1_x86_nexte(TE, W1).raw(), R2));
52}
53
54template <uint8_t R1, uint8_t R2 = R1>
55BOTAN_FORCE_INLINE BOTAN_FN_ISA_SHANI void sha1_x86_rnds8(SIMD_4x32& ABCD,
56 SIMD_4x32& E,
57 const SIMD_4x32& W0,
58 const SIMD_4x32& W1) {
59 auto TE = ABCD;
60 ABCD = SIMD_4x32(_mm_sha1rnds4_epu32(ABCD.raw(), sha1_x86_nexte(E, W0).raw(), R1));
61
62 E = ABCD;
63 ABCD = SIMD_4x32(_mm_sha1rnds4_epu32(ABCD.raw(), sha1_x86_nexte(TE, W1).raw(), R2));
64}
65
66BOTAN_FORCE_INLINE BOTAN_FN_ISA_SHANI SIMD_4x32 rev_words(const SIMD_4x32& v) {
67 return SIMD_4x32(_mm_shuffle_epi32(v.raw(), 0b00011011));
68}
69
70// NOLINTEND(portability-simd-intrinsics)
71
72} // namespace
73
74void BOTAN_FN_ISA_SHANI SHA_1::sha1_compress_x86(digest_type& digest,
75 std::span<const uint8_t> input_span,
76 size_t blocks) {
77 const uint8_t* input = input_span.data();
78
79 SIMD_4x32 ABCD = rev_words(SIMD_4x32::load_le(&digest[0])); // NOLINT(*-container-data-pointer)
80 SIMD_4x32 E0 = SIMD_4x32(0, 0, 0, digest[4]);
81
82 while(blocks > 0) {
83 // Save current hash
84 const auto ABCD_SAVE = ABCD;
85 const auto E0_SAVE = E0;
86
87 auto W0 = rev_words(SIMD_4x32::load_be(input));
88 auto W1 = rev_words(SIMD_4x32::load_be(input + 16));
89 auto W2 = rev_words(SIMD_4x32::load_be(input + 32));
90 auto W3 = rev_words(SIMD_4x32::load_be(input + 48));
91
92 sha1_x86_first8<0>(ABCD, E0, W0, W1);
93 sha1_x86_rnds8<0>(ABCD, E0, W2, W3);
94
95 W0 = sha1_x86_msg1(W0, W1);
96 W1 = sha1_x86_msg1(W1, W2);
97 W0 ^= W2;
98
99 sha1_x86_next_msg(W3, W0, W1, W2);
100 sha1_x86_next_msg(W0, W1, W2, W3);
101 sha1_x86_rnds8<0, 1>(ABCD, E0, W0, W1);
102
103 sha1_x86_next_msg(W1, W2, W3, W0);
104 sha1_x86_next_msg(W2, W3, W0, W1);
105 sha1_x86_rnds8<1>(ABCD, E0, W2, W3);
106
107 sha1_x86_next_msg(W3, W0, W1, W2);
108 sha1_x86_next_msg(W0, W1, W2, W3);
109 sha1_x86_rnds8<1>(ABCD, E0, W0, W1);
110
111 sha1_x86_next_msg(W1, W2, W3, W0);
112 sha1_x86_next_msg(W2, W3, W0, W1);
113 sha1_x86_rnds8<2>(ABCD, E0, W2, W3);
114
115 sha1_x86_next_msg(W3, W0, W1, W2);
116 sha1_x86_next_msg(W0, W1, W2, W3);
117 sha1_x86_rnds8<2>(ABCD, E0, W0, W1);
118
119 sha1_x86_next_msg(W1, W2, W3, W0);
120 sha1_x86_next_msg(W2, W3, W0, W1);
121 sha1_x86_rnds8<2, 3>(ABCD, E0, W2, W3);
122
123 sha1_x86_next_msg(W3, W0, W1, W2);
124 sha1_x86_next_msg(W0, W1, W2, W3);
125 sha1_x86_rnds8<3>(ABCD, E0, W0, W1);
126
127 sha1_x86_next_msg(W1, W2, W3, W0);
128 sha1_x86_next_msg(W2, W3, W0, W1);
129 sha1_x86_rnds8<3>(ABCD, E0, W2, W3);
130
131 ABCD += ABCD_SAVE;
132 E0 = sha1_x86_nexte(E0, E0_SAVE);
133
134 input += 64;
135 blocks--;
136 }
137
138 rev_words(ABCD).store_le(&digest[0]); // NOLINT(*-container-data-pointer)
139 digest[4] = _mm_extract_epi32(E0.raw(), 3);
140}
141
142} // namespace Botan
static void sha1_compress_x86(digest_type &digest, std::span< const uint8_t > blocks, size_t block_count)
Definition sha1_x86.cpp:74
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:174
native_simd_type raw() const noexcept
Definition simd_4x32.h:768
static SIMD_4x32 load_le(const void *in) noexcept
Definition simd_4x32.h:149
#define BOTAN_FORCE_INLINE
Definition compiler.h:87