# FIPS DLL

The Visual Studio solution and project files have a DLL project, Cryptdll, which creates a DLL that provides FIPS 140-2 validated cryptography. The DLL is exercised by the Dlltest project. The DLL provides validated cryptography in accordance with FIPS 140-2, Level 1.

Validated cryptography is a requirement for those doing business in US Federal and US DoD. There are three version of the Crypto++ library that have been validated. They are Crypto++ 5.0.4 (certificate 343), 5.2.3 (certificate 562) and 5.3.0 (certificate 819). Crypto++ 5.0.4 is from 2003 and Crypto++ 5.3.0 is from 2007.

The FIPS DLL is not a general purpose DLL. You should avoid it if possible because it is not easy to work with. Instead, you should link your projects against the static library. If you really need a DLL, then provide a wrapper DLL that links against the static library.

When you see CRYPTOPP_DLL in the source code, you should think FIPS 140-2 Validated DLL, and not a general purpose DLL. That's why the CRYPTOPP_DLL macro is missing from classes like Camellia and Whirlpool.

There is no Crypto++ 5.6 or 5.7 FIPS DLL, and there likely never will be because the process is too expensive.

Note: NIST moved Crypto++ to the Historical Validation List. The Windows binaries are no longer considered validated. You cannot use the binaries and claim validated cryptography for U.S. Federal contracts.

Note: The FIPS DLL was deprecated in December 2018. The project files that are part of the Visual Studio solution are subject to removal. Also see the Crypto++ 8.0 Release Notes and Removal of the FIPS DLL at next Crypto++ release on the mailing list.

Related wiki articles are Nmake (Command Line), MSBuild (Command Line), Visual Studio and Wrapper DLL.

## Avoid the DLL

As stated in the introduction, the FIPS DLL is not a general purpose DLL. You should avoid it if possible because it is not easy to work with. Instead, you should link your projects against the static library.

If you really need a DLL, then provide a wrapper DLL that links against the static library.

The README has the following under MSVC-Specific Information.

On Windows, Crypto++ can be compiled into 3 forms: a static library including all algorithms, a DLL with only FIPS Approved algorithms, and a static library with only algorithms not in the DLL. (FIPS Approved means Approved according to the FIPS 140-2 standard.) The DLL may be used by itself, or it may be used together with the second form of the static library. MSVC project files are included to build all three forms, and sample applications using each of the three forms are also included.

To compile Crypto++ with MSVC, open the "cryptest.dsw" (for MSVC 6 and MSVC .NET 2003) or "cryptest.sln" (for MSVC 2005 - 2010) workspace file and build one or more of the following projects:

• cryptopp - This builds the DLL. Please note that if you wish to use Crypto++ as a FIPS validated module, you must use a pre-built DLL that has undergone the FIPS validation process instead of building your own.
• dlltest - This builds a sample application that only uses the DLL.
• cryptest Non-DLL-Import Configuration - This builds the full static library along with a full test driver.
• cryptest DLL-Import Configuration - This builds a static library containing only algorithms not in the DLL, along with a full test driver that uses both the DLL and the static library.

To use the Crypto++ DLL in your application, #include "dll.h" before including any other Crypto++ header files, and place the DLL in the same directory as your .exe file. dll.h includes the line #pragma comment(lib, "cryptopp") so you don't have to explicitly list the import library in your project settings. To use a static library form of Crypto++, make the "cryptlib" project a dependency of your application project, or specify it as an additional library to link with in your project settings. In either case you should check the compiler options to make sure that the library and your application are using the same C++ run-time libraries and calling conventions.

The DLL also has some basic requirements for memory management. See DLL Memory Management for the details.

## Implementation Details

The FIPS DLL mostly differs from a regular DLL in FIPS program policies and procedures. The same algorithms and C/C++ implementations are used for both validated and non-validated cryptography. However, FIPS 140 policies and procedures means a few additions to a the Crypto++ sources and a few behavioral changes.

The FIPS validated DLL defines CRYPTOPP_ENABLE_COMPLIANCE_WITH_FIPS_140_2. When enabled, the define changes the return value from FIPS_140_2_ComplianceEnabled() to true, and activates some alternate code paths in osrng.h and fips140.cpp.

When FIPS 140 is enabled through the define, FIPS_140_2_ComplianceEnabled() returns true. When true, certain algorithms are checked for correctness using known answer tests (KATs) and Pairwise Consistency checks. When false, the code is written to allow the optimizer to discard it as dead code.

At DLL build time, the program cryptest.exe will embed an HMAC over specific code and data sections in the DLL. It does so using ans SHA-1 HMAC under the constant key, and places it in a variable named s_moduleMac declared in fipstest.cpp.

cryptest.exe knows when to embed the HMAC based on the sub-command mac_dll. cryptest.exe knows where to put it based on a place holder named CRYPTOPP_DUMMY_DLL_MAC. CRYPTOPP_DUMMY_DLL_MAC is a string with a static value of "MAC_51f34b8db820ae8".

At DLL load time, the library integrity checks itself. It is accomplished by verifying a SHA-1 HMAC over specific code and data sections of the PE/PE+ executable. It was placed at build time and it uses the same constant key.

Depending on the result of the integrity check, a state variable of type PowerUpSelfTestStatus called g_powerUpSelfTestStatus maintains the module's state. If the self test fails, then SelfTestFailure is thrown whenever an approved algorithm is used.

At build time and load time, the DLL uses NewIntegrityCheckingMAC to produce the SHA-1 HMAC. The code below is from fipstest.cpp

MessageAuthenticationCode * NewIntegrityCheckingMAC()
{
byte key[] = {0x47, 0x1E, 0x33, 0x96, 0x65, 0xB1, 0x6A, 0xED, 0x0B, 0xF8, 0x6B, 0xFD, 0x01, 0x65, 0x05, 0xCC};
return new HMAC<SHA1>(key, sizeof(key));
}

## Operational Environment

The DLL has specific Operational Environment (OE) requirements. You have to use the DLL on the platform it was validated on, which means the same CPU, OS, service pack level and even C/C++ runtime library. What constitutes an OE is a grey area at times, and selecting a compatibility shim may (or may not) be allowed.

Version Certificate Operational Environment
5.0.4 343 Windows 2000 Professional Operating System, Service Pack 1
5.2.3 562 Windows 2000 Professional Operating System, Service Pack 1
5.3.0 819 Windows XP Professional with SP2 and Windows Server 2003 X64 with SP1

## Approved Algorithms

The DLL only provides core cryptographic classes and functions (listed with its CAVP certificate):

• Skipjack (#17)
• Triple-DES (#512)
• AES (#499)
• SHS (#569)
• DSA (#206)
• RSA (#216)
• ECDSA (#49)
• HMAC (#253)
• RNG (#279)
• Triple-DES MAC (#512)
• Diffie-Hellman

Triple-DES MAC has a dagger () because it is vendor affirmed. That means the CAVP did not test it. Instead, the certificate was issued based on statements made by the Crypto++ project to the CMVP regarding the combination of Triple-DES and HMAC algorithms.

Diffie-Hellman has a double dagger () because it does not have a certificate. It lacks a certificate because the CMVP does not provide methods to test it. That means the certified testing lab could not carry out tests and provide the results to the CMVP. All validated cryptographic libraries endure it, and FIPS 140-3 is supposed to address it.

## Other Algorithms

Notice that the DLL lacks a number of useful algorithms and utility classes. If you need something that is not available in the DLL, you have to add it by hand in a second copy of the library. Adding part of the library as a DLL and the other part of the library as a static LIB is a pain point to say the least.

In this configuration, you will link to the import library at compile time (cryptopp.lib) for the FIPS approved algorithms. At runtime you will link to the DLL (cryptopp.dll). And for the missing classes, you will link to the static library at compile time (cryptlib.lib). All three of these are in the DLL_Output directory.

## Future Alternatives

The FIPS 140 process is expensive, and Crypto++ will likely not undergo another validation. The project recognizes the value of FIPS 140 and the value of write once, run everywhere for users.

The project will likely offer a wrapper in the future. The wrapper will abstract an existing FIPS 140 validation, like wrapping Windows' CryptoNG or Apple's CommonCrypto. Another likely change is the library will provide the implementation within the CryptoPP::FIPS140 namespace.