=============== Introduce =============== The OpenSSL Project is a collaborative effort to develop a robust, commercial-grade, full-featured, and Open Source toolkit implementing the Secure Sockets Layer (SSL v2/v3) and Transport Layer Security (TLS v1) protocols as well as a full-strength general purpose cryptography library managed by a worldwide community of volunteers that use the Internet to communicate, plan, and develop the OpenSSL toolkit and its related documentation. The Federal Information Processing Standard (FIPS) Publication 140-2 is a U.S. government computer security standard used to accredit cryptographic modules. OpenSSL itself is not validated, and never will be. Instead a special carefully defined software component called the OpenSSL FIPS Object Module has been created. This Module was designed for compatibility with OpenSSL so that products using the OpenSSL API can be converted to use validated cryptography with minimal effort. References Documents: https://www.openssl.org/docs/fips.html https://www.openssl.org/docs/fips/UserGuide-2.0.pdf https://www.openssl.org/docs/fips/SecurityPolicy-2.0.16.pdf https://csrc.nist.gov/csrc/media/projects/cryptographic-module-validation-program/documents/security-policies/140sp2398.pdf =============== Building =============== The following software must be built according to the instructions within the UserGuide-2.0.pdf (referenced above). Precompiled versions in this directory were built using the method listed below. In order to build a precompiled version of the binary, you must first construct a target system that includes a target development environment and meta-openssl102-fips layer without feature/openssl-fips The easiest way to do this with Yocto is include this layer [1] and meta-openssl102 [2], and install packagegroup-core-buildessential to image [3] [1] git://git.yoctoproject.org/meta-openssl102-fips [2] git://git.yoctoproject.org/meta-openssl102 Manually set 1.0.2% to openssl preferred version echo "PREFERRED_VERSION_openssl = '1.0.2%'" >> conf/local.conf [3] echo "IMAGE_INSTALL:append = ' packagegroup-core-buildessential'" >> conf/local.conf The easiest way to do this with Wind River Linux is include: --templates features/target-toolchain --templates feature/openssl102 --layers meta-openssl102-fips Note: do not include template feature/openssl-fips Additionally you will need a way to get the openssl-fips module source to the target for the build. Adding ssh/scp is recommended, to add these add the following to your local.conf file: IMAGE_INSTALL:append = " openssh-ssh openssh-scp" If you are building with configurations that have security software enabled, such as SE Linux, you may be required to boot in a non-enforcing mode to follow the steps below. The configuration options necessary to boot into non-enforcing mode may vary depending on the security software and configuration. Building Steps (based on section 4 of the UsersGuide-2.0.pdf): 1. Acquire the OpenSSL FIPS Object Module v2.0. See section 4.1 of the UsersGuide-2.0.pdf for information required to meet CMVP "trusted path" requirements. At the time this document was written: openssl-fips-2.0.16.tar.gz 2. Transfer the verified file to the target system configured with a target compiler. Note: keep in mind the requirements of section 4 and the discussion from section 6.6 of the UsersGuide-2.0.pdf 3. Building the FIPS Object Module (On the target system) gunzip -c openssl-fips-2.0.16.tar.gz | tar xf - cd openssl-fips-2.0.16 # Follow the steps U1 or U2 in Appendx A of the Security Policy # For U1: ./config no-asm make make install # For U2: ./config make make install Selection of U1 vs U2 approach needs to be considered under the configurations in the UserGuide. In some cases, only U1 or U2 will build and test properly for a given system configuration. If one approach does not work, it's advised to try the other approach. Note that as a condition of the FIPS 140-2 validation no other user specified configuration options may be specified. This restriction means that an optional install prefix cannot be specified! However, there is no restriction on subsequent manual relocation of the generated files to the desired final location. In order to support cross compilation with the FIPS Object Module, the 'incore' script needs to also be available. cp util/incore /usr/local/ssl/fips-2.0/bin/. We also advise you to run the test suite as well using: make build_tests ./test/fips_test_suite fullpost 4. Tar up the results and transfer back to your build system (On the target system) In the following refers to one of the defined target architectures such as: x86, x86_64, powerpc, or armv7l tar c /usr/local/ssl | bzip2 > openssl-fips---install.tar.bz2 Move the tar archive back to your host project into a directory accessable by the build system. 5. Configure the build system to enable openssl-fips and locate your custom prebuilt tar archive. For Yocto, in your build directory, edit conf/local.conf, add: IMAGE_INSTALL:append = " openssl-fips-dev" OPENSSL_FIPS_ENABLED = "1" OPENSSL_FIPS_PREBUILT = "" For Wind River Linux, in your build directory, edit conf/local.conf, add: WRTEMPLATE += "feature/openssl-fips" OPENSSL_FIPS_PREBUILT = "" Where path is the location on the host with the prebuilt openssl-fips. Note: If you add or update the archive after trying to build openssl-fips, the system may cache the failure message. You may have to manually clear the cache by running: rm -rf tmp-glibc/cache ======================= Test Examples In Target ======================= 1. OpenSSL FIPS Power-On-Self-Test(POST) $ /test/fips_test_suite post or: $ /fips_test_suite fullpost FIPS-mode test application FIPS 2.0.1 validated test module 12 Jun 2012 DRBG AES-256-CTR DF test started DRBG AES-256-CTR DF test OK 1. Non-Approved cryptographic operation test... a. Included algorithm (D-H)......successful POST started Integrity test started Integrity test OK DRBG AES-256-CTR DF test started DRBG AES-256-CTR DF test OK ... POST Success Testing operation failure with DRBG entropy failure Pairwise Consistency DSA test started Pairwise Consistency DSA test OK DSA key generated OK as expected. DRBG SHA512 test started DRBG SHA512 test OK DRBG entropy fail failed as expected DSA signing failed as expected ECDSA key generation failed as expected. Induced failure test completed with 0 errors successful as expected All tests completed with 0 errors 2. OpenSSL MD5 in FIPS mode $ env OPENSSL_FIPS=1 /usr/bin/openssl md5 /usr/bin/openssl Error setting digest md5 3073021576:error:060A80A3:digital envelope routines:FIPS_DIGESTINIT:disabled for fips:fips_md.c:180: # If no FIPS module linked, openssl will say something else when OPENSSL_FIPS=1 # Try the following command in local host PC. $ env OPENSSL_FIPS=1 /usr/bin/openssl md5 /usr/bin/openssl FIPS mode not supported. 3. OpenSSL MD5 in non-FIPS mode $ /usr/bin/openssl md5 /usr/bin/openssl MD5(/usr/bin/openssl)= 0b6ea5fd013fd1d9d00a95a44acc61c9 4. OpenSSL SHA1 in FIPS mode $ env OPENSSL_FIPS=1 /usr/bin/openssl sha1 /usr/bin/openssl SHA1(/usr/bin/openssl)= 39c978de7152036e73ad2e62f677878f37d3f980 5. OpenSSL SHA1 in non-FIPS mode $ /usr/bin/openssl sha1 /usr/bin/openssl SHA1(/usr/bin/openssl)= 39c978de7152036e73ad2e62f677878f37d3f980 =========================== Example OpenSSL Based Application (Appendix C in UsersGuide-2.0.pdf) =========================== In this application all cryptography is provided through the FIPS Object Module and the FIPS mode initialization is performed via the FIPS_mode_set() call. The command generates a HMAC-SHA-1 digest of an input stream or a file, using the same arbitrary key as the OpenSSL FIPS Module file integrity check 1. Linking with the Shared Object (cross compiling) Linking with the shared object is easiest. That's because the FIPS Capable library build process takes care of a number of items for you, including running fipsld on the shared object libcrypto.so. Then you could dynamicly link the library (-lcrypto) in your recipe as normal. More details at recipe openssl-fips-example do_compile task 2. Linking with the Static Archive (on the target) Linking against the static library is more challenging. That's because you have to set two variables -- CC and FIPSLD_CC and compile with the modified CC. They must be exported because fipsld uses them in child shells. Behind the scenes, fipsld will compile and link fips_premain.c, modify the libcrypto archive, assemble the final program, and embed the fingerprint. On host: edit local.conf to add openssl-fips-example to image $ echo 'IMAGE_INSTALL:append = " openssl-fips-example"' >> conf/local.conf $ bitbake On target: $ cd /usr/lib64/ssl/fips-2.0/test $ make gcc -c fips_hmac.c FIPSLD_CC=gcc /usr/lib64/ssl/fips-2.0//bin/fipsld -o fips_hmac fips_hmac.o /usr/lib64/libcrypto.a -ldl 3. Run applications with fips enabled on target All of them will generate the same HMAC-SHA-1 digest $ cd /usr/lib64/ssl/fips-2.0/test $ ./fips_hmac -v ./fips_hmac.c FIPS mode enabled ae25ad68d9a8cc04075100563a437fa37829afcc # ./fips_hmac.cross -v ./fips_hmac.c FIPS mode enabled ae25ad68d9a8cc04075100563a437fa37829afcc Note this sample command is functionally equivalent to: $ env OPENSSL_FIPS=1 openssl sha1 -hmac etaonrishdlcupfm fips_hmac.c HMAC-SHA1(fips_hmac.c)= ae25ad68d9a8cc04075100563a437fa37829afcc ======================= Known Issues ======================= If the CPU on target machine which building FIPS object module is newer than Nehalem (e.g. Sandy Brigde) or is an Intel Atom processor. Then you may encounter an error when building openssl with the FIPS object module: qemu: uncaught target signal 4 (Illegal instruction). The current processor emulated in qemu is set to Nehalem. But the GCC will use -march=native to enable all instruction subsets supported by the target machine when building FIPS object module. The illegal instruction error will occur if some instruction subsets (e.g AVX/AVX2) are not supported by Nehalem. To check if the CPU is Intel Atom: $ cat /proc/cpuinfo | grep "Atom" To check if the CPU supports AVX/AVX2: $ cat /proc/cpuinfo | grep "avx" Or: $ gcc -dM -E - < /dev/null | grep "AVX" As a workaround, we can specify -march=nehalem in GCC before build the FIPS object module: $ export CC="gcc -march=nehalem" $ ./config [no-asm] $ make $ make install