Botan 3.8.1
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 uint32x4_t ABCD;
25 uint32_t E0;
26
27 // Load magic constants
28 const uint32x4_t C0 = vdupq_n_u32(0x5A827999);
29 const uint32x4_t C1 = vdupq_n_u32(0x6ED9EBA1);
30 const uint32x4_t C2 = vdupq_n_u32(0x8F1BBCDC);
31 const uint32x4_t C3 = vdupq_n_u32(0xCA62C1D6);
32
33 ABCD = vld1q_u32(&digest[0]);
34 E0 = digest[4];
35
36 // Intermediate void* cast due to https://llvm.org/bugs/show_bug.cgi?id=20670
37 const uint32_t* input32 = reinterpret_cast<const uint32_t*>(reinterpret_cast<const void*>(input8.data()));
38
39 while(blocks) {
40 // Save current hash
41 const uint32x4_t ABCD_SAVED = ABCD;
42 const uint32_t E0_SAVED = E0;
43
44 uint32x4_t MSG0, MSG1, MSG2, MSG3;
45 uint32x4_t TMP0, TMP1;
46 uint32_t E1;
47
48 MSG0 = vld1q_u32(input32 + 0);
49 MSG1 = vld1q_u32(input32 + 4);
50 MSG2 = vld1q_u32(input32 + 8);
51 MSG3 = vld1q_u32(input32 + 12);
52
53 MSG0 = vreinterpretq_u32_u8(vrev32q_u8(vreinterpretq_u8_u32(MSG0)));
54 MSG1 = vreinterpretq_u32_u8(vrev32q_u8(vreinterpretq_u8_u32(MSG1)));
55 MSG2 = vreinterpretq_u32_u8(vrev32q_u8(vreinterpretq_u8_u32(MSG2)));
56 MSG3 = vreinterpretq_u32_u8(vrev32q_u8(vreinterpretq_u8_u32(MSG3)));
57
58 TMP0 = vaddq_u32(MSG0, C0);
59 TMP1 = vaddq_u32(MSG1, C0);
60
61 // Rounds 0-3
62 E1 = vsha1h_u32(vgetq_lane_u32(ABCD, 0));
63 ABCD = vsha1cq_u32(ABCD, E0, TMP0);
64 TMP0 = vaddq_u32(MSG2, C0);
65 MSG0 = vsha1su0q_u32(MSG0, MSG1, MSG2);
66
67 // Rounds 4-7
68 E0 = vsha1h_u32(vgetq_lane_u32(ABCD, 0));
69 ABCD = vsha1cq_u32(ABCD, E1, TMP1);
70 TMP1 = vaddq_u32(MSG3, C0);
71 MSG0 = vsha1su1q_u32(MSG0, MSG3);
72 MSG1 = vsha1su0q_u32(MSG1, MSG2, MSG3);
73
74 // Rounds 8-11
75 E1 = vsha1h_u32(vgetq_lane_u32(ABCD, 0));
76 ABCD = vsha1cq_u32(ABCD, E0, TMP0);
77 TMP0 = vaddq_u32(MSG0, C0);
78 MSG1 = vsha1su1q_u32(MSG1, MSG0);
79 MSG2 = vsha1su0q_u32(MSG2, MSG3, MSG0);
80
81 // Rounds 12-15
82 E0 = vsha1h_u32(vgetq_lane_u32(ABCD, 0));
83 ABCD = vsha1cq_u32(ABCD, E1, TMP1);
84 TMP1 = vaddq_u32(MSG1, C1);
85 MSG2 = vsha1su1q_u32(MSG2, MSG1);
86 MSG3 = vsha1su0q_u32(MSG3, MSG0, MSG1);
87
88 // Rounds 16-19
89 E1 = vsha1h_u32(vgetq_lane_u32(ABCD, 0));
90 ABCD = vsha1cq_u32(ABCD, E0, TMP0);
91 TMP0 = vaddq_u32(MSG2, C1);
92 MSG3 = vsha1su1q_u32(MSG3, MSG2);
93 MSG0 = vsha1su0q_u32(MSG0, MSG1, MSG2);
94
95 // Rounds 20-23
96 E0 = vsha1h_u32(vgetq_lane_u32(ABCD, 0));
97 ABCD = vsha1pq_u32(ABCD, E1, TMP1);
98 TMP1 = vaddq_u32(MSG3, C1);
99 MSG0 = vsha1su1q_u32(MSG0, MSG3);
100 MSG1 = vsha1su0q_u32(MSG1, MSG2, MSG3);
101
102 // Rounds 24-27
103 E1 = vsha1h_u32(vgetq_lane_u32(ABCD, 0));
104 ABCD = vsha1pq_u32(ABCD, E0, TMP0);
105 TMP0 = vaddq_u32(MSG0, C1);
106 MSG1 = vsha1su1q_u32(MSG1, MSG0);
107 MSG2 = vsha1su0q_u32(MSG2, MSG3, MSG0);
108
109 // Rounds 28-31
110 E0 = vsha1h_u32(vgetq_lane_u32(ABCD, 0));
111 ABCD = vsha1pq_u32(ABCD, E1, TMP1);
112 TMP1 = vaddq_u32(MSG1, C1);
113 MSG2 = vsha1su1q_u32(MSG2, MSG1);
114 MSG3 = vsha1su0q_u32(MSG3, MSG0, MSG1);
115
116 // Rounds 32-35
117 E1 = vsha1h_u32(vgetq_lane_u32(ABCD, 0));
118 ABCD = vsha1pq_u32(ABCD, E0, TMP0);
119 TMP0 = vaddq_u32(MSG2, C2);
120 MSG3 = vsha1su1q_u32(MSG3, MSG2);
121 MSG0 = vsha1su0q_u32(MSG0, MSG1, MSG2);
122
123 // Rounds 36-39
124 E0 = vsha1h_u32(vgetq_lane_u32(ABCD, 0));
125 ABCD = vsha1pq_u32(ABCD, E1, TMP1);
126 TMP1 = vaddq_u32(MSG3, C2);
127 MSG0 = vsha1su1q_u32(MSG0, MSG3);
128 MSG1 = vsha1su0q_u32(MSG1, MSG2, MSG3);
129
130 // Rounds 40-43
131 E1 = vsha1h_u32(vgetq_lane_u32(ABCD, 0));
132 ABCD = vsha1mq_u32(ABCD, E0, TMP0);
133 TMP0 = vaddq_u32(MSG0, C2);
134 MSG1 = vsha1su1q_u32(MSG1, MSG0);
135 MSG2 = vsha1su0q_u32(MSG2, MSG3, MSG0);
136
137 // Rounds 44-47
138 E0 = vsha1h_u32(vgetq_lane_u32(ABCD, 0));
139 ABCD = vsha1mq_u32(ABCD, E1, TMP1);
140 TMP1 = vaddq_u32(MSG1, C2);
141 MSG2 = vsha1su1q_u32(MSG2, MSG1);
142 MSG3 = vsha1su0q_u32(MSG3, MSG0, MSG1);
143
144 // Rounds 48-51
145 E1 = vsha1h_u32(vgetq_lane_u32(ABCD, 0));
146 ABCD = vsha1mq_u32(ABCD, E0, TMP0);
147 TMP0 = vaddq_u32(MSG2, C2);
148 MSG3 = vsha1su1q_u32(MSG3, MSG2);
149 MSG0 = vsha1su0q_u32(MSG0, MSG1, MSG2);
150
151 // Rounds 52-55
152 E0 = vsha1h_u32(vgetq_lane_u32(ABCD, 0));
153 ABCD = vsha1mq_u32(ABCD, E1, TMP1);
154 TMP1 = vaddq_u32(MSG3, C3);
155 MSG0 = vsha1su1q_u32(MSG0, MSG3);
156 MSG1 = vsha1su0q_u32(MSG1, MSG2, MSG3);
157
158 // Rounds 56-59
159 E1 = vsha1h_u32(vgetq_lane_u32(ABCD, 0));
160 ABCD = vsha1mq_u32(ABCD, E0, TMP0);
161 TMP0 = vaddq_u32(MSG0, C3);
162 MSG1 = vsha1su1q_u32(MSG1, MSG0);
163 MSG2 = vsha1su0q_u32(MSG2, MSG3, MSG0);
164
165 // Rounds 60-63
166 E0 = vsha1h_u32(vgetq_lane_u32(ABCD, 0));
167 ABCD = vsha1pq_u32(ABCD, E1, TMP1);
168 TMP1 = vaddq_u32(MSG1, C3);
169 MSG2 = vsha1su1q_u32(MSG2, MSG1);
170 MSG3 = vsha1su0q_u32(MSG3, MSG0, MSG1);
171
172 // Rounds 64-67
173 E1 = vsha1h_u32(vgetq_lane_u32(ABCD, 0));
174 ABCD = vsha1pq_u32(ABCD, E0, TMP0);
175 TMP0 = vaddq_u32(MSG2, C3);
176 MSG3 = vsha1su1q_u32(MSG3, MSG2);
177 MSG0 = vsha1su0q_u32(MSG0, MSG1, MSG2);
178
179 // Rounds 68-71
180 E0 = vsha1h_u32(vgetq_lane_u32(ABCD, 0));
181 ABCD = vsha1pq_u32(ABCD, E1, TMP1);
182 TMP1 = vaddq_u32(MSG3, C3);
183 MSG0 = vsha1su1q_u32(MSG0, MSG3);
184
185 // Rounds 72-75
186 E1 = vsha1h_u32(vgetq_lane_u32(ABCD, 0));
187 ABCD = vsha1pq_u32(ABCD, E0, TMP0);
188
189 // Rounds 76-79
190 E0 = vsha1h_u32(vgetq_lane_u32(ABCD, 0));
191 ABCD = vsha1pq_u32(ABCD, E1, TMP1);
192
193 // Add state back
194 E0 += E0_SAVED;
195 ABCD = vaddq_u32(ABCD_SAVED, ABCD);
196
197 input32 += 64 / 4;
198 blocks--;
199 }
200
201 // Save digest
202 vst1q_u32(&digest[0], ABCD);
203 digest[4] = E0;
204}
205
206} // 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