• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

randombit / botan / 23486908132

24 Mar 2026 10:53AM UTC coverage: 89.449% (-2.4%) from 91.889%
23486908132

push

github

web-flow
Merge pull request #5479 from randombit/jack/aria-hwaes

Add ARIA implementation using hardware AES instructions

105058 of 117450 relevant lines covered (89.45%)

11951797.05 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

91.85
/src/lib/block/shacal2/shacal2.cpp
1
/*
2
* SHACAL-2
3
* (C) 2017,2020 Jack Lloyd
4
*
5
* Botan is released under the Simplified BSD License (see license.txt)
6
*/
7

8
#include <botan/internal/shacal2.h>
9

10
#include <botan/internal/bit_ops.h>
11
#include <botan/internal/loadstor.h>
12
#include <botan/internal/rotate.h>
13

14
#if defined(BOTAN_HAS_CPUID)
15
   #include <botan/internal/cpuid.h>
16
#endif
17

18
namespace Botan {
19

20
namespace {
21

22
inline void SHACAL2_Fwd(
587,328✔
23
   uint32_t A, uint32_t B, uint32_t C, uint32_t& D, uint32_t E, uint32_t F, uint32_t G, uint32_t& H, uint32_t RK) {
24
   const uint32_t A_rho = rho<2, 13, 22>(A);
587,328✔
25
   const uint32_t E_rho = rho<6, 11, 25>(E);
587,328✔
26

27
   H += E_rho + choose(E, F, G) + RK;
587,328✔
28
   D += H;
587,328✔
29
   H += A_rho + majority(A, B, C);
587,328✔
30
}
587,328✔
31

32
inline void SHACAL2_Rev(
539,136✔
33
   uint32_t A, uint32_t B, uint32_t C, uint32_t& D, uint32_t E, uint32_t F, uint32_t G, uint32_t& H, uint32_t RK) {
34
   const uint32_t A_rho = rho<2, 13, 22>(A);
539,136✔
35
   const uint32_t E_rho = rho<6, 11, 25>(E);
539,136✔
36

37
   H -= A_rho + majority(A, B, C);
539,136✔
38
   D -= H;
539,136✔
39
   H -= E_rho + choose(E, F, G) + RK;
539,136✔
40
}
539,136✔
41

42
}  // namespace
43

44
/*
45
* SHACAL2 Encryption
46
*/
47
void SHACAL2::encrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const {
23,144✔
48
   assert_key_material_set();
23,144✔
49

50
#if defined(BOTAN_HAS_SHACAL2_AVX512)
51
   if(CPUID::has(CPUID::Feature::AVX512)) {
29,952✔
52
      const size_t consumed = avx512_encrypt_blocks(in, out, blocks);
×
53
      in += consumed * BLOCK_SIZE;
×
54
      out += consumed * BLOCK_SIZE;
×
55
      blocks -= consumed;
×
56
   }
57
#endif
58

59
#if defined(BOTAN_HAS_SHACAL2_X86)
60
   if(CPUID::has(CPUID::Feature::SHA)) {
14,976✔
61
      return x86_encrypt_blocks(in, out, blocks);
5,787✔
62
   }
63
#endif
64

65
#if defined(BOTAN_HAS_SHACAL2_ARMV8)
66
   if(CPUID::has(CPUID::Feature::SHA2)) {
67
      return armv8_encrypt_blocks(in, out, blocks);
68
   }
69
#endif
70

71
#if defined(BOTAN_HAS_SHACAL2_AVX2)
72
   if(CPUID::has(CPUID::Feature::AVX2)) {
9,189✔
73
      while(blocks >= 8) {
3,069✔
74
         avx2_encrypt_8(in, out);
6✔
75
         in += 8 * BLOCK_SIZE;
6✔
76
         out += 8 * BLOCK_SIZE;
6✔
77
         blocks -= 8;
6✔
78
      }
79
   }
80
#endif
81

82
#if defined(BOTAN_HAS_SHACAL2_SIMD)
83
   if(CPUID::has(CPUID::Feature::SIMD_4X32)) {
9,189✔
84
      while(blocks >= 4) {
9,213✔
85
         simd_encrypt_4(in, out);
24✔
86
         in += 4 * BLOCK_SIZE;
24✔
87
         out += 4 * BLOCK_SIZE;
24✔
88
         blocks -= 4;
24✔
89
      }
90
   }
91
#endif
92

93
   for(size_t i = 0; i != blocks; ++i) {
18,366✔
94
      uint32_t A = load_be<uint32_t>(in, 0);
9,177✔
95
      uint32_t B = load_be<uint32_t>(in, 1);
9,177✔
96
      uint32_t C = load_be<uint32_t>(in, 2);
9,177✔
97
      uint32_t D = load_be<uint32_t>(in, 3);
9,177✔
98
      uint32_t E = load_be<uint32_t>(in, 4);
9,177✔
99
      uint32_t F = load_be<uint32_t>(in, 5);
9,177✔
100
      uint32_t G = load_be<uint32_t>(in, 6);
9,177✔
101
      uint32_t H = load_be<uint32_t>(in, 7);
9,177✔
102

103
      for(size_t r = 0; r != 64; r += 8) {
82,593✔
104
         SHACAL2_Fwd(A, B, C, D, E, F, G, H, m_RK[r + 0]);
73,416✔
105
         SHACAL2_Fwd(H, A, B, C, D, E, F, G, m_RK[r + 1]);
73,416✔
106
         SHACAL2_Fwd(G, H, A, B, C, D, E, F, m_RK[r + 2]);
73,416✔
107
         SHACAL2_Fwd(F, G, H, A, B, C, D, E, m_RK[r + 3]);
73,416✔
108
         SHACAL2_Fwd(E, F, G, H, A, B, C, D, m_RK[r + 4]);
73,416✔
109
         SHACAL2_Fwd(D, E, F, G, H, A, B, C, m_RK[r + 5]);
73,416✔
110
         SHACAL2_Fwd(C, D, E, F, G, H, A, B, m_RK[r + 6]);
73,416✔
111
         SHACAL2_Fwd(B, C, D, E, F, G, H, A, m_RK[r + 7]);
73,416✔
112
      }
113

114
      store_be(out, A, B, C, D, E, F, G, H);
9,177✔
115

116
      in += BLOCK_SIZE;
9,177✔
117
      out += BLOCK_SIZE;
9,177✔
118
   }
119
}
120

121
/*
122
* SHACAL2 Encryption
123
*/
124
void SHACAL2::decrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const {
16,606✔
125
   assert_key_material_set();
16,606✔
126

127
#if defined(BOTAN_HAS_SHACAL2_AVX512)
128
   if(CPUID::has(CPUID::Feature::AVX512)) {
8,438✔
129
      const size_t consumed = avx512_decrypt_blocks(in, out, blocks);
×
130
      in += consumed * BLOCK_SIZE;
×
131
      out += consumed * BLOCK_SIZE;
×
132
      blocks -= consumed;
×
133
   }
134
#endif
135

136
#if defined(BOTAN_HAS_SHACAL2_AVX2)
137
   if(CPUID::has(CPUID::Feature::AVX2)) {
8,438✔
138
      while(blocks >= 8) {
4,397✔
139
         avx2_decrypt_8(in, out);
43✔
140
         in += 8 * BLOCK_SIZE;
43✔
141
         out += 8 * BLOCK_SIZE;
43✔
142
         blocks -= 8;
43✔
143
      }
144
   }
145
#endif
146

147
#if defined(BOTAN_HAS_SHACAL2_SIMD)
148
   if(CPUID::has(CPUID::Feature::SIMD_4X32)) {
8,438✔
149
      while(blocks >= 4) {
8,463✔
150
         simd_decrypt_4(in, out);
25✔
151
         in += 4 * BLOCK_SIZE;
25✔
152
         out += 4 * BLOCK_SIZE;
25✔
153
         blocks -= 4;
25✔
154
      }
155
   }
156
#endif
157

158
   for(size_t i = 0; i != blocks; ++i) {
16,862✔
159
      uint32_t A = load_be<uint32_t>(in, 0);
8,424✔
160
      uint32_t B = load_be<uint32_t>(in, 1);
8,424✔
161
      uint32_t C = load_be<uint32_t>(in, 2);
8,424✔
162
      uint32_t D = load_be<uint32_t>(in, 3);
8,424✔
163
      uint32_t E = load_be<uint32_t>(in, 4);
8,424✔
164
      uint32_t F = load_be<uint32_t>(in, 5);
8,424✔
165
      uint32_t G = load_be<uint32_t>(in, 6);
8,424✔
166
      uint32_t H = load_be<uint32_t>(in, 7);
8,424✔
167

168
      for(size_t r = 0; r != 64; r += 8) {
75,816✔
169
         SHACAL2_Rev(B, C, D, E, F, G, H, A, m_RK[63 - r]);
67,392✔
170
         SHACAL2_Rev(C, D, E, F, G, H, A, B, m_RK[62 - r]);
67,392✔
171
         SHACAL2_Rev(D, E, F, G, H, A, B, C, m_RK[61 - r]);
67,392✔
172
         SHACAL2_Rev(E, F, G, H, A, B, C, D, m_RK[60 - r]);
67,392✔
173
         SHACAL2_Rev(F, G, H, A, B, C, D, E, m_RK[59 - r]);
67,392✔
174
         SHACAL2_Rev(G, H, A, B, C, D, E, F, m_RK[58 - r]);
67,392✔
175
         SHACAL2_Rev(H, A, B, C, D, E, F, G, m_RK[57 - r]);
67,392✔
176
         SHACAL2_Rev(A, B, C, D, E, F, G, H, m_RK[56 - r]);
67,392✔
177
      }
178

179
      store_be(out, A, B, C, D, E, F, G, H);
8,424✔
180

181
      in += BLOCK_SIZE;
8,424✔
182
      out += BLOCK_SIZE;
8,424✔
183
   }
184
}
8,438✔
185

186
bool SHACAL2::has_keying_material() const {
57,673✔
187
   return !m_RK.empty();
57,673✔
188
}
189

190
/*
191
* SHACAL2 Key Schedule
192
*/
193
void SHACAL2::key_schedule(std::span<const uint8_t> key) {
12,278✔
194
   const uint32_t RC[64] = {
12,278✔
195
      0x428A2F98, 0x71374491, 0xB5C0FBCF, 0xE9B5DBA5, 0x3956C25B, 0x59F111F1, 0x923F82A4, 0xAB1C5ED5,
196
      0xD807AA98, 0x12835B01, 0x243185BE, 0x550C7DC3, 0x72BE5D74, 0x80DEB1FE, 0x9BDC06A7, 0xC19BF174,
197
      0xE49B69C1, 0xEFBE4786, 0x0FC19DC6, 0x240CA1CC, 0x2DE92C6F, 0x4A7484AA, 0x5CB0A9DC, 0x76F988DA,
198
      0x983E5152, 0xA831C66D, 0xB00327C8, 0xBF597FC7, 0xC6E00BF3, 0xD5A79147, 0x06CA6351, 0x14292967,
199
      0x27B70A85, 0x2E1B2138, 0x4D2C6DFC, 0x53380D13, 0x650A7354, 0x766A0ABB, 0x81C2C92E, 0x92722C85,
200
      0xA2BFE8A1, 0xA81A664B, 0xC24B8B70, 0xC76C51A3, 0xD192E819, 0xD6990624, 0xF40E3585, 0x106AA070,
201
      0x19A4C116, 0x1E376C08, 0x2748774C, 0x34B0BCB5, 0x391C0CB3, 0x4ED8AA4A, 0x5B9CCA4F, 0x682E6FF3,
202
      0x748F82EE, 0x78A5636F, 0x84C87814, 0x8CC70208, 0x90BEFFFA, 0xA4506CEB, 0xBEF9A3F7, 0xC67178F2};
203

204
   if(m_RK.empty()) {
12,278✔
205
      m_RK.resize(64);
12,274✔
206
   } else {
207
      clear_mem(m_RK.data(), m_RK.size());
4✔
208
   }
209

210
   load_be(m_RK.data(), key.data(), key.size() / 4);
12,278✔
211

212
   for(size_t i = 16; i != 64; ++i) {
601,622✔
213
      const uint32_t sigma0_15 = sigma<7, 18, 3>(m_RK[i - 15]);
589,344✔
214
      const uint32_t sigma1_2 = sigma<17, 19, 10>(m_RK[i - 2]);
589,344✔
215
      m_RK[i] = m_RK[i - 16] + sigma0_15 + m_RK[i - 7] + sigma1_2;
589,344✔
216
   }
217

218
   for(size_t i = 0; i != 64; ++i) {
798,070✔
219
      m_RK[i] += RC[i];
785,792✔
220
   }
221
}
12,278✔
222

223
size_t SHACAL2::parallelism() const {
12,309✔
224
#if defined(BOTAN_HAS_SHACAL2_AVX512)
225
   if(CPUID::has(CPUID::Feature::AVX512)) {
12,309✔
226
      return 16;
227
   }
228
#endif
229

230
#if defined(BOTAN_HAS_SHACAL2_X86)
231
   if(CPUID::has(CPUID::Feature::SHA)) {
12,309✔
232
      return 2;
233
   }
234
#endif
235

236
#if defined(BOTAN_HAS_SHACAL2_ARMV8)
237
   if(CPUID::has(CPUID::Feature::SHA2)) {
238
      return 2;
239
   }
240
#endif
241

242
#if defined(BOTAN_HAS_SHACAL2_AVX2)
243
   if(CPUID::has(CPUID::Feature::AVX2)) {
9,189✔
244
      return 8;
245
   }
246
#endif
247

248
#if defined(BOTAN_HAS_SHACAL2_SIMD)
249
   if(CPUID::has(CPUID::Feature::SIMD_4X32)) {
6,126✔
250
      return 4;
6,126✔
251
   }
252
#endif
253

254
   return 1;
255
}
256

257
std::string SHACAL2::provider() const {
4,084✔
258
#if defined(BOTAN_HAS_SHACAL2_AVX512)
259
   if(auto feat = CPUID::check(CPUID::Feature::AVX512)) {
4,084✔
260
      return *feat;
×
261
   }
×
262
#endif
263

264
#if defined(BOTAN_HAS_SHACAL2_X86)
265
   if(auto feat = CPUID::check(CPUID::Feature::SHA)) {
4,084✔
266
      return *feat;
2,042✔
267
   }
1,021✔
268
#endif
269

270
#if defined(BOTAN_HAS_SHACAL2_ARMV8)
271
   if(auto feat = CPUID::check(CPUID::Feature::SHA2)) {
272
      return *feat;
273
   }
274
#endif
275

276
#if defined(BOTAN_HAS_SHACAL2_AVX2)
277
   if(auto feat = CPUID::check(CPUID::Feature::AVX2)) {
3,063✔
278
      return *feat;
2,042✔
279
   }
1,021✔
280
#endif
281

282
#if defined(BOTAN_HAS_SHACAL2_SIMD)
283
   if(auto feat = CPUID::check(CPUID::Feature::SIMD_4X32)) {
2,042✔
284
      return *feat;
4,084✔
285
   }
2,042✔
286
#endif
287

288
   return "base";
×
289
}
290

291
/*
292
* Clear memory of sensitive data
293
*/
294
void SHACAL2::clear() {
8,178✔
295
   zap(m_RK);
8,178✔
296
}
8,178✔
297

298
}  // namespace Botan
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc