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

randombit / botan / 12993346889

27 Jan 2025 04:15PM UTC coverage: 91.248% (+0.002%) from 91.246%
12993346889

push

github

butteronarchbtw
add (s)afi encoding & decoding

94261 of 103302 relevant lines covered (91.25%)

11708235.22 hits per line

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

95.83
/src/lib/utils/cpuid/cpuid.cpp
1
/*
2
* Runtime CPU detection
3
* (C) 2009,2010,2013,2017,2023 Jack Lloyd
4
*
5
* Botan is released under the Simplified BSD License (see license.txt)
6
*/
7

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

10
#include <botan/exceptn.h>
11
#include <botan/types.h>
12
#include <botan/internal/parsing.h>
13
#include <ostream>
14

15
#if defined(BOTAN_HAS_OS_UTILS)
16
   #include <botan/internal/os_utils.h>
17
#endif
18

19
namespace Botan {
20

21
//static
22
std::string CPUID::to_string() {
19✔
23
   std::vector<std::string> flags;
19✔
24

25
   auto append_fn = [&](bool flag, const char* flag_name) {
399✔
26
      if(flag) {
380✔
27
         flags.push_back(flag_name);
442✔
28
      }
29
   };
380✔
30

31
   // NOLINTNEXTLINE(*-macro-usage)
32
#define CPUID_PRINT(flag) append_fn(has_##flag(), #flag)
33

34
#if defined(BOTAN_TARGET_CPU_IS_X86_FAMILY)
35
   CPUID_PRINT(rdtsc);
19✔
36

37
   CPUID_PRINT(sse2);
19✔
38
   CPUID_PRINT(ssse3);
19✔
39
   CPUID_PRINT(avx2);
19✔
40

41
   CPUID_PRINT(bmi2);
19✔
42
   CPUID_PRINT(adx);
19✔
43
   CPUID_PRINT(gfni);
19✔
44

45
   CPUID_PRINT(aes_ni);
19✔
46
   CPUID_PRINT(clmul);
19✔
47
   CPUID_PRINT(rdrand);
19✔
48
   CPUID_PRINT(rdseed);
19✔
49
   CPUID_PRINT(intel_sha);
19✔
50
   CPUID_PRINT(intel_sha512);
19✔
51

52
   CPUID_PRINT(avx2_vaes);
19✔
53
   CPUID_PRINT(avx2_clmul);
19✔
54

55
   CPUID_PRINT(avx512);
19✔
56
   CPUID_PRINT(avx512_aes);
19✔
57
   CPUID_PRINT(avx512_clmul);
19✔
58

59
   CPUID_PRINT(intel_sm3);
19✔
60
   CPUID_PRINT(intel_sm4);
19✔
61

62
#elif defined(BOTAN_TARGET_CPU_IS_PPC_FAMILY)
63
   CPUID_PRINT(altivec);
64
   CPUID_PRINT(power_crypto);
65
   CPUID_PRINT(darn_rng);
66
#elif defined(BOTAN_TARGET_CPU_IS_ARM_FAMILY)
67
   CPUID_PRINT(neon);
68
   CPUID_PRINT(arm_sve);
69

70
   CPUID_PRINT(arm_sha1);
71
   CPUID_PRINT(arm_sha2);
72
   CPUID_PRINT(arm_aes);
73
   CPUID_PRINT(arm_pmull);
74
   CPUID_PRINT(arm_sha2_512);
75
   CPUID_PRINT(arm_sha3);
76
   CPUID_PRINT(arm_sm3);
77
   CPUID_PRINT(arm_sm4);
78
#else
79
   BOTAN_UNUSED(append_fn);
80
#endif
81

82
#undef CPUID_PRINT
83

84
   return string_join(flags, ' ');
38✔
85
}
19✔
86

87
//static
88
void CPUID::initialize() {
5,625✔
89
   state() = CPUID_Data();
5,625✔
90
}
5,625✔
91

92
namespace {
93

94
// Returns true if big-endian
95
bool runtime_check_if_big_endian() {
13,010✔
96
   // Check runtime endian
97
   const uint32_t endian32 = 0x01234567;
13,010✔
98
   const uint8_t* e8 = reinterpret_cast<const uint8_t*>(&endian32);
13,010✔
99

100
   bool is_big_endian = false;
13,010✔
101

102
   if(e8[0] == 0x01 && e8[1] == 0x23 && e8[2] == 0x45 && e8[3] == 0x67) {
13,010✔
103
      is_big_endian = true;
104
   } else if(e8[0] == 0x67 && e8[1] == 0x45 && e8[2] == 0x23 && e8[3] == 0x01) {
13,010✔
105
      is_big_endian = false;
106
   } else {
107
      throw Internal_Error("Unexpected endian at runtime, neither big nor little");
108
   }
109

110
   // If we were compiled with a known endian, verify it matches at runtime
111
#if defined(BOTAN_TARGET_CPU_IS_LITTLE_ENDIAN)
112
   BOTAN_ASSERT(!is_big_endian, "Build and runtime endian match");
13,010✔
113
#elif defined(BOTAN_TARGET_CPU_IS_BIG_ENDIAN)
114
   BOTAN_ASSERT(is_big_endian, "Build and runtime endian match");
115
#endif
116

117
   return is_big_endian;
13,010✔
118
}
119

120
#if defined(BOTAN_CPUID_HAS_DETECTION)
121
uint32_t cleared_cpuid_bits() {
13,010✔
122
   uint32_t cleared = 0;
13,010✔
123

124
   #if defined(BOTAN_HAS_OS_UTILS)
125
   std::string clear_cpuid_env;
13,010✔
126
   if(OS::read_env_variable(clear_cpuid_env, "BOTAN_CLEAR_CPUID")) {
13,010✔
127
      for(const auto& cpuid : split_on(clear_cpuid_env, ',')) {
336✔
128
         for(auto& bit : CPUID::bit_from_string(cpuid)) {
336✔
129
            cleared |= bit;
168✔
130
         }
168✔
131
      }
168✔
132
   }
133
   #endif
134

135
   return cleared;
13,010✔
136
}
13,010✔
137
#endif
138

139
}  // namespace
140

141
CPUID::CPUID_Data::CPUID_Data() {
13,010✔
142
   m_processor_features = 0;
13,010✔
143

144
#if defined(BOTAN_CPUID_HAS_DETECTION)
145
   m_processor_features = detect_cpu_features(~cleared_cpuid_bits());
13,010✔
146
#endif
147

148
   m_processor_features |= CPUID::CPUID_INITIALIZED_BIT;
13,010✔
149

150
   if(runtime_check_if_big_endian()) {
13,010✔
151
      m_processor_features |= CPUID::CPUID_IS_BIG_ENDIAN_BIT;
152
   }
153
}
13,010✔
154

155
std::vector<CPUID::CPUID_bits> CPUID::bit_from_string(std::string_view tok) {
211✔
156
#if defined(BOTAN_TARGET_CPU_IS_X86_FAMILY)
157
   if(tok == "sse2" || tok == "simd") {
232✔
158
      return {CPUID::CPUID_SSE2_BIT};
7✔
159
   } else if(tok == "ssse3") {
204✔
160
      return {CPUID::CPUID_SSSE3_BIT};
6✔
161
   } else if(tok == "aesni" || tok == "aes_ni") {
208✔
162
      // aes_ni is the string printed on the console when running "botan cpuid"
163
      return {CPUID::CPUID_AESNI_BIT};
8✔
164
   } else if(tok == "clmul") {
194✔
165
      return {CPUID::CPUID_CLMUL_BIT};
3✔
166
   } else if(tok == "avx2") {
191✔
167
      return {CPUID::CPUID_AVX2_BIT};
6✔
168
   } else if(tok == "avx512") {
185✔
169
      return {CPUID::CPUID_AVX512_BIT};
2✔
170
   }
171
   // there were two if statements testing "sha" and "intel_sha" separately; combined
172
   else if(tok == "sha" || tok == "intel_sha") {
188✔
173
      return {CPUID::CPUID_SHA_BIT};
4✔
174
   } else if(tok == "rdtsc") {
179✔
175
      return {CPUID::CPUID_RDTSC_BIT};
1✔
176
   } else if(tok == "bmi2") {
178✔
177
      return {CPUID::CPUID_BMI_BIT};
4✔
178
   } else if(tok == "adx") {
174✔
179
      return {CPUID::CPUID_ADX_BIT};
1✔
180
   } else if(tok == "gfni") {
173✔
181
      return {CPUID::CPUID_GFNI_BIT};
1✔
182
   } else if(tok == "rdrand") {
172✔
183
      return {CPUID::CPUID_RDRAND_BIT};
1✔
184
   } else if(tok == "rdseed") {
171✔
185
      return {CPUID::CPUID_RDSEED_BIT};
1✔
186
   } else if(tok == "avx512_aes") {
170✔
187
      return {CPUID::CPUID_AVX512_AES_BIT};
×
188
   } else if(tok == "avx512_clmul") {
170✔
189
      return {CPUID::CPUID_AVX512_CLMUL_BIT};
×
190
   } else if(tok == "avx2_vaes") {
170✔
191
      return {CPUID::CPUID_AVX2_AES_BIT};
2✔
192
   } else if(tok == "avx2_clmul") {
168✔
193
      return {CPUID::CPUID_AVX2_CLMUL_BIT};
156✔
194
   } else if(tok == "intel_sm3") {
12✔
195
      return {CPUID::CPUID_SM3_BIT};
×
196
   } else if(tok == "intel_sm4") {
12✔
197
      return {CPUID::CPUID_SM4_BIT};
×
198
   }
199

200
#elif defined(BOTAN_TARGET_CPU_IS_PPC_FAMILY)
201
   if(tok == "altivec" || tok == "simd") {
202
      return {CPUID::CPUID_ALTIVEC_BIT};
203
   } else if(tok == "power_crypto") {
204
      return {CPUID::CPUID_POWER_CRYPTO_BIT};
205
   } else if(tok == "darn_rng") {
206
      return {CPUID::CPUID_DARN_BIT};
207
   }
208

209
#elif defined(BOTAN_TARGET_CPU_IS_ARM_FAMILY)
210
   if(tok == "neon" || tok == "simd") {
211
      return {CPUID::CPUID_ARM_NEON_BIT};
212
   } else if(tok == "arm_sve") {
213
      return {CPUID::CPUID_ARM_SVE_BIT};
214
   } else if(tok == "armv8sha1" || tok == "arm_sha1") {
215
      return {CPUID::CPUID_ARM_SHA1_BIT};
216
   } else if(tok == "armv8sha2" || tok == "arm_sha2") {
217
      return {CPUID::CPUID_ARM_SHA2_BIT};
218
   } else if(tok == "armv8aes" || tok == "arm_aes") {
219
      return {CPUID::CPUID_ARM_AES_BIT};
220
   } else if(tok == "armv8pmull" || tok == "arm_pmull") {
221
      return {CPUID::CPUID_ARM_PMULL_BIT};
222
   } else if(tok == "armv8sha3" || tok == "arm_sha3") {
223
      return {CPUID::CPUID_ARM_SHA3_BIT};
224
   } else if(tok == "armv8sha2_512" || tok == "arm_sha2_512") {
225
      return {CPUID::CPUID_ARM_SHA2_512_BIT};
226
   } else if(tok == "armv8sm3" || tok == "arm_sm3") {
227
      return {CPUID::CPUID_ARM_SM3_BIT};
228
   } else if(tok == "armv8sm4" || tok == "arm_sm4") {
229
      return {CPUID::CPUID_ARM_SM4_BIT};
230
   }
231

232
#else
233
   BOTAN_UNUSED(tok);
234
#endif
235

236
   return {};
12✔
237
}
238

239
}  // 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