Coverage Report

Created: 2026-06-28 06:23

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/boringssl/crypto/cpu_arm_linux.h
Line
Count
Source
1
// Copyright 2018 The BoringSSL Authors
2
//
3
// Licensed under the Apache License, Version 2.0 (the "License");
4
// you may not use this file except in compliance with the License.
5
// You may obtain a copy of the License at
6
//
7
//     https://www.apache.org/licenses/LICENSE-2.0
8
//
9
// Unless required by applicable law or agreed to in writing, software
10
// distributed under the License is distributed on an "AS IS" BASIS,
11
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
// See the License for the specific language governing permissions and
13
// limitations under the License.
14
15
#ifndef OPENSSL_HEADER_CRYPTO_CPU_ARM_LINUX_H
16
#define OPENSSL_HEADER_CRYPTO_CPU_ARM_LINUX_H
17
18
#include <openssl/base.h>
19
20
#include <assert.h>
21
22
#include <string_view>
23
24
#include "internal.h"
25
26
27
BSSL_NAMESPACE_BEGIN
28
namespace armcap {
29
30
// The cpuinfo parser lives in a header file so it may be accessible from
31
// cross-platform fuzzers without adding code to those platforms normally.
32
33
#define CRYPTO_HWCAP_NEON (1 << 12)
34
35
// See /usr/include/asm/hwcap.h on an ARM installation for the source of
36
// these values.
37
// We add the prefix "CRYPTO_" to the definitions so as not to collide with
38
// some versions of glibc (>= 2.41) that expose them through <sys/auxv.h>.
39
2
#define CRYPTO_HWCAP2_AES (1 << 0)
40
6
#define CRYPTO_HWCAP2_PMULL (1 << 1)
41
4
#define CRYPTO_HWCAP2_SHA1 (1 << 2)
42
7
#define CRYPTO_HWCAP2_SHA2 (1 << 3)
43
44
// SplitStringView finds the first occurrence of `sep` in `in` and, if found,
45
// sets `*out_left` and `*out_right` to `in` split before and after `sep`, and
46
// returns true. If not found, it returns false.
47
inline bool SplitStringView(std::string_view *out_left,
48
                            std::string_view *out_right, std::string_view in,
49
666k
                            char sep) {
50
666k
  auto pos = in.find(sep);
51
666k
  if (pos == std::string_view::npos) {
52
264k
    return false;
53
264k
  }
54
401k
  *out_left = in.substr(0, pos);
55
401k
  *out_right = in.substr(pos + 1);
56
401k
  return true;
57
666k
}
58
59
// GetDelimited reads a `sep`-delimited entry from `s`, writing it to `out` and
60
// updating `s` to point beyond it. It returns true on success and false if `s`
61
// is empty. If `s` has no copies of `sep` and is non-empty, it reads the entire
62
// string to `out`.
63
399k
inline bool GetDelimited(std::string_view *s, std::string_view *out, char sep) {
64
399k
  if (s->empty()) {
65
2.83k
    return false;
66
2.83k
  }
67
397k
  if (!SplitStringView(out, s, *s, sep)) {
68
    // `s` had no instances of `sep`. Return the entire string.
69
1.82k
    *out = *s;
70
1.82k
    *s = std::string_view();
71
1.82k
  }
72
397k
  return true;
73
399k
}
74
75
// TrimStringView removes leading and trailing whitespace from `s`.
76
6.79k
inline std::string_view TrimStringView(std::string_view s) {
77
6.79k
  size_t pos = s.find_first_not_of(" \t");
78
6.79k
  if (pos == std::string_view::npos) {
79
2.43k
    return {};
80
2.43k
  }
81
4.36k
  s = s.substr(pos);
82
4.36k
  pos = s.find_last_not_of(" \t");
83
4.36k
  assert(pos != std::string_view::npos);
84
4.36k
  return s.substr(0, pos + 1);
85
4.36k
}
86
87
// ExtractCpuinfoField extracts a /proc/cpuinfo field named `field` from `in`.
88
// If found, it returns the value. Otherwise, it returns the empty string.
89
inline std::string_view ExtractCpuinfoField(std::string_view in,
90
634
                                            std::string_view field) {
91
  // Process `in` one line at a time.
92
634
  std::string_view line;
93
269k
  while (GetDelimited(&in, &line, '\n')) {
94
269k
    std::string_view key, value;
95
269k
    if (!SplitStringView(&key, &value, line, ':')) {
96
262k
      continue;
97
262k
    }
98
6.48k
    if (TrimStringView(key) == field) {
99
313
      return TrimStringView(value);
100
313
    }
101
6.48k
  }
102
103
321
  return {};
104
634
}
105
106
// HasListItem treats `list` as a space-separated list of items and returns
107
// whether `item` is contained in `list`.
108
2.53k
inline bool HasListItem(std::string_view list, std::string_view item) {
109
2.53k
  std::string_view feature;
110
130k
  while (GetDelimited(&list, &feature, ' ')) {
111
128k
    if (feature == item) {
112
19
      return true;
113
19
    }
114
128k
  }
115
2.51k
  return false;
116
2.53k
}
117
118
// GetHWCAP2FromCpuinfo returns an equivalent ARM `AT_HWCAP2` value from
119
// `cpuinfo`.
120
634
inline unsigned long GetHWCAP2FromCpuinfo(std::string_view cpuinfo) {
121
634
  std::string_view features = ExtractCpuinfoField(cpuinfo, "Features");
122
634
  unsigned long ret = 0;
123
634
  if (HasListItem(features, "aes")) {
124
2
    ret |= CRYPTO_HWCAP2_AES;
125
2
  }
126
634
  if (HasListItem(features, "pmull")) {
127
6
    ret |= CRYPTO_HWCAP2_PMULL;
128
6
  }
129
634
  if (HasListItem(features, "sha1")) {
130
4
    ret |= CRYPTO_HWCAP2_SHA1;
131
4
  }
132
634
  if (HasListItem(features, "sha2")) {
133
7
    ret |= CRYPTO_HWCAP2_SHA2;
134
7
  }
135
634
  return ret;
136
634
}
137
138
}  // namespace armcap
139
BSSL_NAMESPACE_END
140
141
#endif  // OPENSSL_HEADER_CRYPTO_CPU_ARM_LINUX_H