1// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
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#include <openssl/ec.h>
17#include <openssl/ec_key.h>
18#include <openssl/err.h>
19#include <openssl/evp.h>
20
21#include "../../evp/internal.h"
22#include "../../internal.h"
23#include "internal.h"
24
25#if defined(BORINGSSL_FIPS)
26
27#define STATE_UNLOCKED 0
28
29// fips_service_indicator_state is a thread-local structure that stores the
30// state of the FIPS service indicator.
31struct fips_service_indicator_state {
32  // lock_state records the number of times the indicator has been locked.
33  // When it is zero (i.e. |STATE_UNLOCKED|) then the indicator can be updated.
34  uint64_t lock_state;
35  // counter is the indicator state. It is incremented when an approved service
36  // completes.
37  uint64_t counter;
38};
39
40// service_indicator_get returns a pointer to the |fips_service_indicator_state|
41// for the current thread. It returns NULL on error.
42//
43// FIPS 140-3 requires that the module should provide the service indicator
44// for approved services irrespective of whether the user queries it or not.
45// Hence, it is lazily initialized in any call to an approved service.
46static struct fips_service_indicator_state *service_indicator_get(void) {
47  struct fips_service_indicator_state *indicator =
48      reinterpret_cast<fips_service_indicator_state *>(CRYPTO_get_thread_local(
49          OPENSSL_THREAD_LOCAL_FIPS_SERVICE_INDICATOR_STATE));
50
51  if (indicator == NULL) {
52    indicator = reinterpret_cast<fips_service_indicator_state *>(
53        OPENSSL_malloc(sizeof(struct fips_service_indicator_state)));
54    if (indicator == NULL) {
55      return NULL;
56    }
57
58    indicator->lock_state = STATE_UNLOCKED;
59    indicator->counter = 0;
60
61    if (!CRYPTO_set_thread_local(
62            OPENSSL_THREAD_LOCAL_FIPS_SERVICE_INDICATOR_STATE, indicator,
63            OPENSSL_free)) {
64      OPENSSL_PUT_ERROR(CRYPTO, ERR_R_INTERNAL_ERROR);
65      return NULL;
66    }
67  }
68
69  return indicator;
70}
71
72static uint64_t service_indicator_get_counter(void) {
73  struct fips_service_indicator_state *indicator = service_indicator_get();
74  if (indicator == NULL) {
75    return 0;
76  }
77  return indicator->counter;
78}
79
80uint64_t FIPS_service_indicator_before_call(void) {
81  return service_indicator_get_counter();
82}
83
84uint64_t FIPS_service_indicator_after_call(void) {
85  return service_indicator_get_counter();
86}
87
88void FIPS_service_indicator_update_state(void) {
89  struct fips_service_indicator_state *indicator = service_indicator_get();
90  if (indicator && indicator->lock_state == STATE_UNLOCKED) {
91    indicator->counter++;
92  }
93}
94
95void FIPS_service_indicator_lock_state(void) {
96  struct fips_service_indicator_state *indicator = service_indicator_get();
97  if (indicator == NULL) {
98    return;
99  }
100
101  // |FIPS_service_indicator_lock_state| and
102  // |FIPS_service_indicator_unlock_state| should not under/overflow in normal
103  // operation. They are still checked and errors added to facilitate testing in
104  // service_indicator_test.cc. This should only happen if lock/unlock are
105  // called in an incorrect order or multiple times in the same function.
106  const uint64_t new_state = indicator->lock_state + 1;
107  if (new_state < indicator->lock_state) {
108    // Overflow. This would imply that our call stack length has exceeded a
109    // |uint64_t| which impossible on a 64-bit system.
110    abort();
111  }
112
113  indicator->lock_state = new_state;
114}
115
116void FIPS_service_indicator_unlock_state(void) {
117  struct fips_service_indicator_state *indicator = service_indicator_get();
118  if (indicator == NULL) {
119    return;
120  }
121
122  if (indicator->lock_state == 0) {
123    abort();
124  }
125
126  indicator->lock_state--;
127}
128
129void AEAD_GCM_verify_service_indicator(const EVP_AEAD_CTX *ctx) {
130  const size_t key_len = EVP_AEAD_key_length(ctx->aead);
131  if (key_len == 16 || key_len == 32) {
132    FIPS_service_indicator_update_state();
133  }
134}
135
136void AEAD_CCM_verify_service_indicator(const EVP_AEAD_CTX *ctx) {
137  if (EVP_AEAD_key_length(ctx->aead) == 16 && ctx->tag_len == 4) {
138    FIPS_service_indicator_update_state();
139  }
140}
141
142// is_ec_fips_approved returns one if the curve corresponding to the given NID
143// is FIPS approved, and zero otherwise.
144static int is_ec_fips_approved(int curve_nid) {
145  switch (curve_nid) {
146    case NID_secp224r1:
147    case NID_X9_62_prime256v1:
148    case NID_secp384r1:
149    case NID_secp521r1:
150      return 1;
151    default:
152      return 0;
153  }
154}
155
156// is_md_fips_approved_for_signing returns one if the given message digest type
157// is FIPS approved for signing, and zero otherwise.
158static int is_md_fips_approved_for_signing(int md_type) {
159  switch (md_type) {
160    case NID_sha224:
161    case NID_sha256:
162    case NID_sha384:
163    case NID_sha512:
164    case NID_sha512_256:
165      return 1;
166    default:
167      return 0;
168  }
169}
170
171// is_md_fips_approved_for_verifying returns one if the given message digest
172// type is FIPS approved for verifying, and zero otherwise.
173static int is_md_fips_approved_for_verifying(int md_type) {
174  switch (md_type) {
175    case NID_sha224:
176    case NID_sha256:
177    case NID_sha384:
178    case NID_sha512:
179    case NID_sha512_256:
180      return 1;
181    default:
182      return 0;
183  }
184}
185
186static void evp_md_ctx_verify_service_indicator(const EVP_MD_CTX *ctx,
187                                                int (*md_ok)(int md_type)) {
188  if (EVP_MD_CTX_get0_md(ctx) == NULL) {
189    // Signature schemes without a prehash are currently never FIPS approved.
190    return;
191  }
192
193  EVP_PKEY_CTX *const pctx = ctx->pctx;
194  const EVP_PKEY *const pkey = EVP_PKEY_CTX_get0_pkey(pctx);
195  const int pkey_type = EVP_PKEY_id(pkey);
196  const int md_type = EVP_MD_CTX_type(ctx);
197
198  // EVP_PKEY_RSA_PSS SPKIs aren't supported.
199  if (pkey_type == EVP_PKEY_RSA) {
200    // Message digest used in the private key should be of the same type
201    // as the given one, so we extract the MD type from the |EVP_PKEY|
202    // and compare it with the type in |ctx|.
203    const EVP_MD *pctx_md;
204    if (!EVP_PKEY_CTX_get_signature_md(pctx, &pctx_md)) {
205      goto err;
206    }
207    if (EVP_MD_type(pctx_md) != md_type) {
208      goto err;
209    }
210
211    int padding;
212    if (!EVP_PKEY_CTX_get_rsa_padding(pctx, &padding)) {
213      goto err;
214    }
215    if (padding == RSA_PKCS1_PSS_PADDING) {
216      int salt_len;
217      const EVP_MD *mgf1_md;
218      if (!EVP_PKEY_CTX_get_rsa_pss_saltlen(pctx, &salt_len) ||
219          !EVP_PKEY_CTX_get_rsa_mgf1_md(pctx, &mgf1_md) ||
220          (salt_len != RSA_PSS_SALTLEN_DIGEST &&
221           salt_len != (int)EVP_MD_size(pctx_md)) ||
222          EVP_MD_type(mgf1_md) != md_type) {
223        // Only PSS where saltLen == hashLen is tested with ACVP. Cases with
224        // non-standard padding functions are also excluded.
225        goto err;
226      }
227    }
228
229    // The approved RSA key sizes for signing are 2048, 3072 and 4096 bits.
230    // Note: |EVP_PKEY_size| returns the size in bytes.
231    size_t pkey_size = EVP_PKEY_size(ctx->pctx->pkey.get());
232
233    // Check if the MD type and the RSA key size are approved.
234    if (md_ok(md_type) &&
235        (pkey_size == 256 || pkey_size == 384 || pkey_size == 512)) {
236      FIPS_service_indicator_update_state();
237    }
238  } else if (pkey_type == EVP_PKEY_EC) {
239    // Check if the MD type and the elliptic curve are approved.
240    if (md_ok(md_type) &&
241        is_ec_fips_approved(EC_GROUP_get_curve_name(
242            EC_KEY_get0_group(EVP_PKEY_get0_EC_KEY(ctx->pctx->pkey.get()))))) {
243      FIPS_service_indicator_update_state();
244    }
245  }
246
247err:
248  // Ensure that junk errors aren't left on the queue.
249  ERR_clear_error();
250}
251
252void EC_KEY_keygen_verify_service_indicator(const EC_KEY *eckey) {
253  if (is_ec_fips_approved(EC_GROUP_get_curve_name(EC_KEY_get0_group(eckey)))) {
254    FIPS_service_indicator_update_state();
255  }
256}
257
258void ECDH_verify_service_indicator(const EC_KEY *ec_key) {
259  if (is_ec_fips_approved(EC_GROUP_get_curve_name(EC_KEY_get0_group(ec_key)))) {
260    FIPS_service_indicator_update_state();
261  }
262}
263
264void EVP_Cipher_verify_service_indicator(const EVP_CIPHER_CTX *ctx) {
265  switch (EVP_CIPHER_CTX_nid(ctx)) {
266    case NID_aes_128_ecb:
267    case NID_aes_192_ecb:
268    case NID_aes_256_ecb:
269
270    case NID_aes_128_cbc:
271    case NID_aes_192_cbc:
272    case NID_aes_256_cbc:
273
274    case NID_aes_128_ctr:
275    case NID_aes_192_ctr:
276    case NID_aes_256_ctr:
277      FIPS_service_indicator_update_state();
278  }
279}
280
281void EVP_DigestVerify_verify_service_indicator(const EVP_MD_CTX *ctx) {
282  return evp_md_ctx_verify_service_indicator(ctx,
283                                             is_md_fips_approved_for_verifying);
284}
285
286void EVP_DigestSign_verify_service_indicator(const EVP_MD_CTX *ctx) {
287  return evp_md_ctx_verify_service_indicator(ctx,
288                                             is_md_fips_approved_for_signing);
289}
290
291void HMAC_verify_service_indicator(const EVP_MD *evp_md) {
292  switch (EVP_MD_type(evp_md)) {
293    case NID_sha1:
294    case NID_sha224:
295    case NID_sha256:
296    case NID_sha384:
297    case NID_sha512:
298    case NID_sha512_256:
299      FIPS_service_indicator_update_state();
300      break;
301  }
302}
303
304void TLSKDF_verify_service_indicator(const EVP_MD *md) {
305  // HMAC-SHA{256, 384, 512} are approved for use in the KDF in TLS 1.2. These
306  // Key Derivation functions are to be used in the context of the TLS protocol.
307  switch (EVP_MD_type(md)) {
308    case NID_sha256:
309    case NID_sha384:
310    case NID_sha512:
311      FIPS_service_indicator_update_state();
312      break;
313  }
314}
315
316#else
317
318uint64_t FIPS_service_indicator_before_call(void) { return 0; }
319
320uint64_t FIPS_service_indicator_after_call(void) {
321  // One is returned so that the return value is always greater than zero, the
322  // return value of |FIPS_service_indicator_before_call|. This makes everything
323  // report as "approved" in non-FIPS builds.
324  return 1;
325}
326
327#endif  // BORINGSSL_FIPS
328