Botan 3.10.0
Crypto and TLS for C&
sha1_armv8.cpp
Go to the documentation of this file.
1/*
2* SHA-1 using CPU instructions in ARMv8
3*
4* Contributed by Jeffrey Walton. Based on public domain code by
5* Johannes Schneiders, Skip Hovsmith and Barry O'Rourke.
6*
7* Botan is released under the Simplified BSD License (see license.txt)
8*/
9
10#include <botan/internal/sha1.h>
11
12#include <botan/internal/isa_extn.h>
13#include <arm_neon.h>
14
15namespace Botan {
16
17/*
18* SHA-1 using CPU instructions in ARMv8
19*/
20//static
21void BOTAN_FN_ISA_SHA2 SHA_1::sha1_armv8_compress_n(digest_type& digest,
22 std::span<const uint8_t> input8,
23 size_t blocks) {
24 // Load magic constants
25 const uint32x4_t C0 = vdupq_n_u32(0x5A827999);
26 const uint32x4_t C1 = vdupq_n_u32(0x6ED9EBA1);
27 const uint32x4_t C2 = vdupq_n_u32(0x8F1BBCDC);
28 const uint32x4_t C3 = vdupq_n_u32(0xCA62C1D6);
29
30 uint32x4_t ABCD = vld1q_u32(&digest[0]); // NOLINT(*-container-data-pointer)
31 uint32_t E0 = digest[4];
32
33 const uint32_t* input32 = reinterpret_cast<const uint32_t*>(input8.data());
34
35 while(blocks > 0) {
36 // Save current hash
37 const uint32x4_t ABCD_SAVED = ABCD;
38 const uint32_t E0_SAVED = E0;
39
40 uint32x4_t MSG0 = vld1q_u32(input32 + 0);
41 uint32x4_t MSG1 = vld1q_u32(input32 + 4);
42 uint32x4_t MSG2 = vld1q_u32(input32 + 8);
43 uint32x4_t MSG3 = vld1q_u32(input32 + 12);
44
45 MSG0 = vreinterpretq_u32_u8(vrev32q_u8(vreinterpretq_u8_u32(MSG0)));
46 MSG1 = vreinterpretq_u32_u8(vrev32q_u8(vreinterpretq_u8_u32(MSG1)));
47 MSG2 = vreinterpretq_u32_u8(vrev32q_u8(vreinterpretq_u8_u32(MSG2)));
48 MSG3 = vreinterpretq_u32_u8(vrev32q_u8(vreinterpretq_u8_u32(MSG3)));
49
50 uint32x4_t TMP0 = vaddq_u32(MSG0, C0);
51 uint32x4_t TMP1 = vaddq_u32(MSG1, C0);
52
53 // Rounds 0-3
54 uint32_t E1 = vsha1h_u32(vgetq_lane_u32(ABCD, 0));
55 ABCD = vsha1cq_u32(ABCD, E0, TMP0);
56 TMP0 = vaddq_u32(MSG2, C0);
57 MSG0 = vsha1su0q_u32(MSG0, MSG1, MSG2);
58
59 // Rounds 4-7
60 E0 = vsha1h_u32(vgetq_lane_u32(ABCD, 0));
61 ABCD = vsha1cq_u32(ABCD, E1, TMP1);
62 TMP1 = vaddq_u32(MSG3, C0);
63 MSG0 = vsha1su1q_u32(MSG0, MSG3);
64 MSG1 = vsha1su0q_u32(MSG1, MSG2, MSG3);
65
66 // Rounds 8-11
67 E1 = vsha1h_u32(vgetq_lane_u32(ABCD, 0));
68 ABCD = vsha1cq_u32(ABCD, E0, TMP0);
69 TMP0 = vaddq_u32(MSG0, C0);
70 MSG1 = vsha1su1q_u32(MSG1, MSG0);
71 MSG2 = vsha1su0q_u32(MSG2, MSG3, MSG0);
72
73 // Rounds 12-15
74 E0 = vsha1h_u32(vgetq_lane_u32(ABCD, 0));
75 ABCD = vsha1cq_u32(ABCD, E1, TMP1);
76 TMP1 = vaddq_u32(MSG1, C1);
77 MSG2 = vsha1su1q_u32(MSG2, MSG1);
78 MSG3 = vsha1su0q_u32(MSG3, MSG0, MSG1);
79
80 // Rounds 16-19
81 E1 = vsha1h_u32(vgetq_lane_u32(ABCD, 0));
82 ABCD = vsha1cq_u32(ABCD, E0, TMP0);
83 TMP0 = vaddq_u32(MSG2, C1);
84 MSG3 = vsha1su1q_u32(MSG3, MSG2);
85 MSG0 = vsha1su0q_u32(MSG0, MSG1, MSG2);
86
87 // Rounds 20-23
88 E0 = vsha1h_u32(vgetq_lane_u32(ABCD, 0));
89 ABCD = vsha1pq_u32(ABCD, E1, TMP1);
90 TMP1 = vaddq_u32(MSG3, C1);
91 MSG0 = vsha1su1q_u32(MSG0, MSG3);
92 MSG1 = vsha1su0q_u32(MSG1, MSG2, MSG3);
93
94 // Rounds 24-27
95 E1 = vsha1h_u32(vgetq_lane_u32(ABCD, 0));
96 ABCD = vsha1pq_u32(ABCD, E0, TMP0);
97 TMP0 = vaddq_u32(MSG0, C1);
98 MSG1 = vsha1su1q_u32(MSG1, MSG0);
99 MSG2 = vsha1su0q_u32(MSG2, MSG3, MSG0);
100
101 // Rounds 28-31
102 E0 = vsha1h_u32(vgetq_lane_u32(ABCD, 0));
103 ABCD = vsha1pq_u32(ABCD, E1, TMP1);
104 TMP1 = vaddq_u32(MSG1, C1);
105 MSG2 = vsha1su1q_u32(MSG2, MSG1);
106 MSG3 = vsha1su0q_u32(MSG3, MSG0, MSG1);
107
108 // Rounds 32-35
109 E1 = vsha1h_u32(vgetq_lane_u32(ABCD, 0));
110 ABCD = vsha1pq_u32(ABCD, E0, TMP0);
111 TMP0 = vaddq_u32(MSG2, C2);
112 MSG3 = vsha1su1q_u32(MSG3, MSG2);
113 MSG0 = vsha1su0q_u32(MSG0, MSG1, MSG2);
114
115 // Rounds 36-39
116 E0 = vsha1h_u32(vgetq_lane_u32(ABCD, 0));
117 ABCD = vsha1pq_u32(ABCD, E1, TMP1);
118 TMP1 = vaddq_u32(MSG3, C2);
119 MSG0 = vsha1su1q_u32(MSG0, MSG3);
120 MSG1 = vsha1su0q_u32(MSG1, MSG2, MSG3);
121
122 // Rounds 40-43
123 E1 = vsha1h_u32(vgetq_lane_u32(ABCD, 0));
124 ABCD = vsha1mq_u32(ABCD, E0, TMP0);
125 TMP0 = vaddq_u32(MSG0, C2);
126 MSG1 = vsha1su1q_u32(MSG1, MSG0);
127 MSG2 = vsha1su0q_u32(MSG2, MSG3, MSG0);
128
129 // Rounds 44-47
130 E0 = vsha1h_u32(vgetq_lane_u32(ABCD, 0));
131 ABCD = vsha1mq_u32(ABCD, E1, TMP1);
132 TMP1 = vaddq_u32(MSG1, C2);
133 MSG2 = vsha1su1q_u32(MSG2, MSG1);
134 MSG3 = vsha1su0q_u32(MSG3, MSG0, MSG1);
135
136 // Rounds 48-51
137 E1 = vsha1h_u32(vgetq_lane_u32(ABCD, 0));
138 ABCD = vsha1mq_u32(ABCD, E0, TMP0);
139 TMP0 = vaddq_u32(MSG2, C2);
140 MSG3 = vsha1su1q_u32(MSG3, MSG2);
141 MSG0 = vsha1su0q_u32(MSG0, MSG1, MSG2);
142
143 // Rounds 52-55
144 E0 = vsha1h_u32(vgetq_lane_u32(ABCD, 0));
145 ABCD = vsha1mq_u32(ABCD, E1, TMP1);
146 TMP1 = vaddq_u32(MSG3, C3);
147 MSG0 = vsha1su1q_u32(MSG0, MSG3);
148 MSG1 = vsha1su0q_u32(MSG1, MSG2, MSG3);
149
150 // Rounds 56-59
151 E1 = vsha1h_u32(vgetq_lane_u32(ABCD, 0));
152 ABCD = vsha1mq_u32(ABCD, E0, TMP0);
153 TMP0 = vaddq_u32(MSG0, C3);
154 MSG1 = vsha1su1q_u32(MSG1, MSG0);
155 MSG2 = vsha1su0q_u32(MSG2, MSG3, MSG0);
156
157 // Rounds 60-63
158 E0 = vsha1h_u32(vgetq_lane_u32(ABCD, 0));
159 ABCD = vsha1pq_u32(ABCD, E1, TMP1);
160 TMP1 = vaddq_u32(MSG1, C3);
161 MSG2 = vsha1su1q_u32(MSG2, MSG1);
162 MSG3 = vsha1su0q_u32(MSG3, MSG0, MSG1);
163
164 // Rounds 64-67
165 E1 = vsha1h_u32(vgetq_lane_u32(ABCD, 0));
166 ABCD = vsha1pq_u32(ABCD, E0, TMP0);
167 TMP0 = vaddq_u32(MSG2, C3);
168 MSG3 = vsha1su1q_u32(MSG3, MSG2);
169 MSG0 = vsha1su0q_u32(MSG0, MSG1, MSG2);
170
171 // Rounds 68-71
172 E0 = vsha1h_u32(vgetq_lane_u32(ABCD, 0));
173 ABCD = vsha1pq_u32(ABCD, E1, TMP1);
174 TMP1 = vaddq_u32(MSG3, C3);
175
176 // Rounds 72-75
177 E1 = vsha1h_u32(vgetq_lane_u32(ABCD, 0));
178 ABCD = vsha1pq_u32(ABCD, E0, TMP0);
179
180 // Rounds 76-79
181 E0 = vsha1h_u32(vgetq_lane_u32(ABCD, 0));
182 ABCD = vsha1pq_u32(ABCD, E1, TMP1);
183
184 // Add state back
185 E0 += E0_SAVED;
186 ABCD = vaddq_u32(ABCD_SAVED, ABCD);
187
188 input32 += 64 / 4;
189 blocks--;
190 }
191
192 // Save digest
193 vst1q_u32(&digest[0], ABCD); // NOLINT(*-container-data-pointer)
194 digest[4] = E0;
195}
196
197} // namespace Botan
static void sha1_armv8_compress_n(digest_type &digest, std::span< const uint8_t > blocks, size_t block_count)
secure_vector< uint32_t > digest_type
Definition sha1.h:20