# Use Tink to meet FIPS 140-2 security requirements

> [!NOTE]
> **Note:** This is only supported in the C++ version of Tink at the moment.

Tink itself is not
[FIPS 140-2](https://csrc.nist.gov/publications/detail/fips/140/2/final) validated. However, it supports several FIPS
140-2 approved algorithms and the underlying implementations *can* utilize
validated cryptographic modules like
[BoringSSLs BoringCrypto](https://csrc.nist.gov/projects/cryptographic-module-validation-program/certificate/3678). Tink includes a
[WORKSPACE](https://github.com/tink-crypto/tink-cc/blob/main/third_party/boringssl_fips) for building BoringSSL in FIPS mode.

Note that the workspace gives no inherent guarantee that your use of BoringSSL
is FIPS compliant. We strongly recommend that you read the official
[security policy](https://csrc.nist.gov/CSRC/media/projects/cryptographic-module-validation-program/documents/security-policies/140sp3678.pdf) for BoringCrypto.

## Supported algorithms

The following algorithms in Tink are approved according to
[FIPS 140-2](https://csrc.nist.gov/publications/detail/fips/140/2/final) (see more information at
[FIPS 140-2 Annex A](https://csrc.nist.gov/CSRC/media/Publications/fips/140/2/final/documents/fips1402annexa.pdf)):

- Authenticated Encryption
  - AES-GCM
  - AES-CTR-HMAC-SHA256
- MAC
  - HMAC-SHA256
  - AES-CMAC
- Digital Signatures
  - ECDSA
  - RSA-SSA-PKCS1
  - RSA-SSA-PSS

## FIPS-only mode in C++

If you are required to use FIPS 140-2 approved algorithms and validated
implementations, you can build Tink in FIPS-only mode. This restricts
usage to approved algorithms *and* checks if Tink is utilizing a validated
cryptographic module.

This changes the behavior of Tink in the following ways:

- `Register()` functions only register algorithms that have a FIPS validated implementation. This means that you are *only* able to use Keysets for algorithms that use a validated cryptographic module.
- Tink checks if BoringSSL has been built with the BoringCrypto module. Calls to primitives return an `INTERNAL` error when the module is not available.
- Using primitives in `subtle/` is restricted to algorithms that utilize a validated cryptographic module.

### BoringCrypto

Tink uses [BoringCrypto](https://csrc.nist.gov/projects/cryptographic-module-validation-program/certificate/3678)
in C++ to provide access to a validated cryptographic module. Its current
validation status imposes the following additional constraints on available
algorithms when in FIPS-only mode:

- AES-CMAC has not been validated and is not available
- RSA-SSA-PKCS1 is restricted to 3072-bit modulus
- RSA-SSA-PSS is restricted to 3072-bit modulus

To use the BoringCrypto module with Bazel, you can uncomment the
`local_repository` definition for `boringssl` in the [C++
WORKSPACE](https://github.com/google/tink/blob/master/cc/WORKSPACE).

### Enable at compile time

To build Tink in FIPS-only mode, set a flag at compile time:

    bazel build ... --//third_party/tink/cc/config:use_only_fips=True

If you want to check at runtime whether Tink has been built in FIPS only mode,
you can include the header `internal/fips_utils.h` which provides the constant
`kUseOnlyFips`.

If you are *not* building Tink in FIPS only mode, it can still utilize
validated implementations for *some* algorithms but not restrict the usage of
other algorithms.

### Enable at run time

As an alternative to building Tink in FIPS-only mode, you can call
`crypto::tink::RestrictToFips()` from `config/tink_fips.h` which sets a flag
at runtime to enable the restrictions to FIPS primitives.

WARNING: If you use the runtime option, then `crypto::tink::RestrictToFips()`
must be called before handling any key material, registering key manager, or
other Tink functionalities. Additionally, you must ensure that BoringSSL has
been built with the BoringCrypto module, otherwise Tink does not allow you to
process any data.