1// Copyright 2017 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#include <openssl/crypto.h>
16
17#include "../../internal.h"
18#include "../delocate.h"
19
20
21int FIPS_mode(void) {
22#if defined(BORINGSSL_FIPS) && !defined(OPENSSL_ASAN)
23  return 1;
24#else
25  return 0;
26#endif
27}
28
29int FIPS_mode_set(int on) { return on == FIPS_mode(); }
30
31const char *FIPS_module_name(void) { return "BoringCrypto"; }
32
33int CRYPTO_has_asm(void) {
34#if defined(OPENSSL_NO_ASM)
35  return 0;
36#else
37  return 1;
38#endif
39}
40
41uint32_t FIPS_version(void) {
42  return 0;
43}
44
45int FIPS_query_algorithm_status(const char *algorithm) {
46#if defined(BORINGSSL_FIPS)
47  static const char kApprovedAlgorithms[][13] = {
48    "AES-CBC",
49    "AES-CCM",
50    "AES-CTR",
51    "AES-ECB",
52    "AES-GCM",
53    "AES-KW",
54    "AES-KWP",
55    "ctrDRBG",
56    "ECC-SSC",
57    "ECDSA-sign",
58    "ECDSA-verify",
59    "FFC-SSC",
60    "HMAC",
61    "RSA-sign",
62    "RSA-verify",
63    "SHA-1",
64    "SHA2-224",
65    "SHA2-256",
66    "SHA2-384",
67    "SHA2-512",
68    "SHA2-512/256",
69  };
70  for (size_t i = 0; i < OPENSSL_ARRAY_SIZE(kApprovedAlgorithms); i++) {
71    if (strcmp(algorithm, kApprovedAlgorithms[i]) == 0) {
72      return 1;
73    }
74  }
75#endif  // BORINGSSL_FIPS
76
77  return 0;
78}
79
80#if defined(BORINGSSL_FIPS_COUNTERS)
81
82size_t FIPS_read_counter(enum fips_counter_t counter) {
83  size_t index = (size_t)counter;
84  if (index > fips_counter_max) {
85    abort();
86  }
87
88  const size_t *array = reinterpret_cast<const size_t *>(
89      CRYPTO_get_thread_local(OPENSSL_THREAD_LOCAL_FIPS_COUNTERS));
90  if (!array) {
91    return 0;
92  }
93
94  return array[index];
95}
96
97void boringssl_fips_inc_counter(enum fips_counter_t counter) {
98  size_t index = (size_t)counter;
99  if (index > fips_counter_max) {
100    abort();
101  }
102
103  size_t *array = reinterpret_cast<size_t *>(
104      CRYPTO_get_thread_local(OPENSSL_THREAD_LOCAL_FIPS_COUNTERS));
105  if (!array) {
106    const size_t num_bytes = sizeof(size_t) * (fips_counter_max + 1);
107    array = reinterpret_cast<size_t *>(OPENSSL_zalloc(num_bytes));
108    if (!array) {
109      return;
110    }
111
112    if (!CRYPTO_set_thread_local(OPENSSL_THREAD_LOCAL_FIPS_COUNTERS, array,
113                                 OPENSSL_free)) {
114      // |OPENSSL_free| has already been called by |CRYPTO_set_thread_local|.
115      return;
116    }
117  }
118
119  array[index]++;
120}
121
122#else
123
124size_t FIPS_read_counter(enum fips_counter_t counter) { return 0; }
125
126// boringssl_fips_inc_counter is a no-op, inline function in internal.h in this
127// case. That should let the compiler optimise away the callsites.
128
129#endif
130