From d8dd3ce56dd98f147d0178a929ffa94decd07107 Mon Sep 17 00:00:00 2001
From: Anderson Toshiyuki Sasaki <ansasaki@redhat.com>
Date: May 14 2020 16:32:00 +0000
Subject: distribution/fips: Update to work on Fedora


On Fedora, crypto-policies and fips-mode-setup are available.

---

diff --git a/distribution/fips/Makefile b/distribution/fips/Makefile
index 71c57e0..635dd29 100644
--- a/distribution/fips/Makefile
+++ b/distribution/fips/Makefile
@@ -1,12 +1,12 @@
 # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 #
 #   Makefile of /distribution/Library/fips
-#   Description: A set of helpers for FIPS related testing.
+#   Description: A set of helpers for FIPS 140 testing.
 #   Author: Ondrej Moris <omoris@redhat.com>
 #
 # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 #
-#   Copyright (c) 2012 Red Hat, Inc. All rights reserved.
+#   Copyright (c) 2018 Red Hat, Inc. All rights reserved.
 #
 #   This copyrighted material is made available to anyone wishing
 #   to use, modify, copy, or redistribute it subject to the terms
@@ -29,7 +29,7 @@ export TESTVERSION=1.0
 
 BUILT_FILES=
 
-FILES=$(METADATA) runtest.sh lib.sh Makefile
+FILES=$(METADATA) runtest.sh lib.sh Makefile rstrnt-package-workaround.sh
 
 .PHONY: all install download clean
 
@@ -50,9 +50,9 @@ $(METADATA): Makefile
 	@echo "Name:            $(TEST)" >> $(METADATA)
 	@echo "TestVersion:     $(TESTVERSION)" >> $(METADATA)
 	@echo "Path:            $(TEST_DIR)" >> $(METADATA)
-	@echo "Description:     A set of helpers for FIPS related testing" >> $(METADATA)
+	@echo "Description:     A set of helpers for FIPS 140 testing" >> $(METADATA)
 	@echo "Type:            Library" >> $(METADATA)
-	@echo "Requires:        coreutils" >> $(METADATA)
+	@echo "Requires:        coreutils crypto-policies fips-mode-setup" >> $(METADATA)
 	@echo "TestTime:        30m" >> $(METADATA)
 	@echo "Provides:        library(distribution/fips)" >> $(METADATA)
 	@echo "License:         GPLv2" >> $(METADATA)
diff --git a/distribution/fips/lib.sh b/distribution/fips/lib.sh
index bd4f81b..b549b64 100755
--- a/distribution/fips/lib.sh
+++ b/distribution/fips/lib.sh
@@ -3,12 +3,12 @@
 # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 #
 #   lib.sh of /distribution/Library/fips
-#   Description: A set of helpers for FIPS related testing.
+#   Description: A set of helpers for FIPS 140 testing.
 #   Author: Ondrej Moris <omoris@redhat.com>
 #
 # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 #
-#   Copyright (c) 2012 Red Hat, Inc. All rights reserved.
+#   Copyright (c) 2018 Red Hat, Inc. All rights reserved.
 #
 #   This copyrighted material is made available to anyone wishing
 #   to use, modify, copy, or redistribute it subject to the terms
@@ -33,51 +33,252 @@ true <<'=cut'
 
 =head1 NAME
 
-distribution/fips - a set of helpers for FIPS related testing
+distribution/fips - a set of helpers for FIPS 140 testing
 
 =head1 DESCRIPTION
 
-This is a library intended for FIPS related testing. Currently it contains
-just a single function checking FIPS status. The library is intended to be
-extended.
+This is a library intended for FIPS 140 testing. It can check status of
+FIPS 140 mode and it can enable FIPS 140 mode. Importing this library
+with misconfigured (neither fully disabled nor fully enabled) FIPS 140 mode
+will produce an error.
 
 =cut
 
 # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-#   Variables
+#   Internal Functions and Variabled
 # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-true <<'=cut'
-=pod
+# Directory with this library.
+_fipsLIBDIR=""
 
-=head1 GLOBAL VARIABLES
+function _workarounds {
 
-=over
+    local ret_val=0 
 
-=item fipsBOOTDEV
+    if rlIsRHEL ">=8"; then
 
-Boot device.
+        # On RHEL-8, rpm cannot verify digests of rpms using MD5 digest in FIPS 140.
+        # Unfortunately, older test rpms are do not have neither SHA1 nor SHA256 and
+        # hence cannot be installed. Test installation si done by restraint and we 
+        # have to workaround it not to check digests.
+        rlRun "cp ${_fipsLIBDIR}/rstrnt-package-workaround.sh /usr/local/bin && \
+               chmod a+x /usr/local/bin/rstrnt-package-workaround.sh && \
+               echo 'RSTRNT_PKG_CMD=/usr/local/bin/rstrnt-package-workaround.sh' >/usr/share/restraint/pkg_commands.d/rhel" 0 \
+              "Apply workaround for installation test rpms with MD5 digest" || ret_val=1
+    fi
 
-=item fipsBOOTCONFIG
+    return $ret_val
+}
 
-Location of bootloader configuration file.
+function _disablePrelink {
+    if rlCheckRpm "prelink"; then
 
-=back
+        # Sometimes prelink complains about files being changed during
+        # unlinking so let's run a simple yum command to make sure yum
+        # is not running in the background ("somehow") and wait for it
+        # to finish (yum automatically uses lockfiles for that).
+        if ! rlIsRHEL '<5'; then
+            rlRun "yum list --showduplicates prelink" 0 "Wait for yum"
+        fi
+
+        # Make sure prelink job is not running now (e.g. started by cron).
+        rlRun "killall prelink" 0,1 "Kill all prelinks"
+        rlRun "sed -i 's/PRELINKING=.*/PRELINKING=no/g' /etc/sysconfig/prelink" 0 "Configure system not to use prelink"
+        rlRun "sync" 0 "Commit change to disk"
+        rlRun "killall prelink" 0,1 "Kill all prelinks (again)"
+        rlRun "prelink -u -a" 0 "Un-prelink the system"
+    fi
+
+    return 0
+}
+
+function _enforceModulusBits {
+    if ! rlIsRHEL '<6.5' 5 4; then
+        if ! grep 'OPENSSL_ENFORCE_MODULUS_BITS' /etc/environment; then
+            rlRun "echo 'OPENSSL_ENFORCE_MODULUS_BITS=true' >> /etc/environment" 0 "Enable OPENSSL_ENFORCE_MODULUS_BITS (env)"
+        fi
+        rlRun "echo 'export OPENSSL_ENFORCE_MODULUS_BITS=true' > /etc/profile.d/openssl.sh && \
+               chmod +x /etc/profile.d/openssl.sh && \
+               echo 'setenv OPENSSL_ENFORCE_MODULUS_BITS true' > /etc/profile.d/openssl.csh && \
+               chmod +x /etc/profile.d/openssl.csh" 0 "Enable OPENSSL_ENFORCE_MODULUS_BITS (profiles)"
+
+        # Beaker tests don't use profile or environment so we have to set
+        # their environment separately.
+        BEAKERLIB=${BEAKERLIB:-"/usr/share/beakerlib"}
+        rlRun "mkdir -p ${BEAKERLIB}/plugins/ && \
+               echo 'export OPENSSL_ENFORCE_MODULUS_BITS=true' > ${BEAKERLIB}/plugins/openssl-fips-override.sh && \
+               chmod +x ${BEAKERLIB}/plugins/openssl-fips-override.sh" 0 "Enable OPENSSL_ENFORCE_MODULUS_BITS (beaker)"
+    fi
+
+    return 0
+}
+
+function _enableFIPS {
+
+    if ! rlIsRHEL "<8"; then
+
+        # Use crypto-policies to set-up FIPS 140 mode.
+        rlRun "fips-mode-setup --enable" 0 "Enable FIPS 140 mode"
+
+    elif rlIsRHEL ">=6"; then
+
+        # Install dracut and dracut-fips on RHEL7 and RHEL6.
+        rlCheckRpm "dracut" || rlRun "yum --enablerepo='*' install dracut -y" 0 "Install dracut"
+        rlCheckRpm "dracut-fips" || rlRun "yum --enablerepo='*' install dracut-fips -y" 0 "Install dracut-fips"
+
+        if grep -qE '\<aes\>' /proc/cpuinfo && \
+           grep -qE '\<GenuineIntel\>' /proc/cpuinfo; then
+
+            rlLogInfo "AES instruction set on Intel CPU detected"
+
+            if [ "$IGNORE_AESNI" == "1" ]; then
+                rlLogInfo "Installation of dracut-fips-aesni skipped"
+            else
+                rlCheckRpm "dracut-fips-aesni" || \
+                    rlRun "yum --enablerepo='*' install -y dracut-fips-aesni" 0 "Install dracut-fips-aesni"
+            fi
+        else
+            rlLogInfo "Intel AES instruction set not detected"
+            rlCheckRpm "dracut-fips-aesni" && rlRun "yum remove -y dracut-fips-aesni" 0 "Remove dracut-fips-aesni"
+        fi
+
+        # Re-generate initramfs to include FIPS dracut modules.
+        rlRun "dracut -v -f" 0 "Regenerate initramfs"
+    fi
+
+    return 0
+}
+
+function _modifyBootloader {
+
+    # On RHEL-8, fips-mode-setup binary modifies bootloader.
+    rlIsRHEL "<8" || return 0
+
+    local arch=$(uname -i)
+    local sed_options="--follow-symlinks"
+
+    rlIsRHEL 5 && sed_options="-c"
+
+    # Get block device name.
+    local boot_dev=$(df -P /boot/ | tail -1 | awk '{print $1}')
+    if [ -z "$boot_dev" ]; then
+        rlFail "Can't detect /boot device name, cannot continue!"
+        rlLog "df /boot/ | tail -1"
+        return 1
+    fi
+
+    if [[ "${USE_UUID:-yes}" != "no" && "${USE_UUID:-1}" != "0" ]]; then
+
+        # Get block device UUID, see BZ 1014527 if UUIDs don't work.
+        local old_boot_dev=$boot_dev
+        boot_dev="UUID=$(blkid -s UUID -o value $old_boot_dev)"
+        if [ "$boot_dev" == "UUID=" ]; then
+            rlFail "Cannnot detect /boot device UUID, cannot continue!"
+            rlLog "blkid -s UUID -o value $old_boot_dev"
+            return 1
+        fi
+    fi
+
+    local bootconf=""
+    case $arch in
+        i386|x86_64)
+
+            # Since RHEL-7.4-20170421.1, grub2-efi packages were renamed
+            # to grub2-efi-ia32 and grub2-efi-x64
+            if rpm -qa | grep "grub2-efi"; then
+                bootconf="/boot/efi/EFI/redhat/grub.cfg"
+                rlRun "sed -i $sed_options 's/ fips=[01] boot=$boot_dev/ /g' $bootconf" 0 \
+                    "Reset GRUB fips configuration"
+                rlRun "sed -i $sed_options 's|\(vmlinuz.*\)|\1 fips=1 boot=$boot_dev|g' $bootconf" 0 \
+                    "Setup GRUB fips configuration"
+            elif rpm -qa | grep "grub2"; then
+                bootconf="/boot/grub2/grub.cfg"
+                rlRun "sed -i $sed_options 's/ fips=[01] boot=$boot_dev/ /g' $bootconf" 0 \
+                    "Reset GRUB fips configuration"
+                rlRun "sed -i $sed_options 's|\(vmlinuz.*\)|\1 fips=1 boot=$boot_dev|g' $bootconf" 0 \
+                    "Setup GRUB fips configuration"
+            elif mount | grep -i efi; then
+                bootconf="/boot/efi/EFI/redhat/grub.conf"
+                rlRun "sed -i $sed_options 's/ fips=[01] boot=$boot_dev/ /g' $bootconf" 0 \
+                    "Reset GRUB fips configuration"
+                rlRun "sed -i $sed_options 's|\(vmlinuz.*\)|\1 fips=1 boot=$boot_dev|g' $bootconf" 0 \
+                    "Setup GRUB fips configuration"
+            else
+                bootconf="/boot/grub/grub.conf"
+                rlRun "sed -i $sed_options 's/ fips=[01] boot=$boot_dev/ /g' $bootconf" 0 \
+                    "Reset GRUB fips configuration"
+                rlRun "sed -i $sed_options 's|\(kernel.*\)|\1 fips=1 boot=$boot_dev|g' $bootconf" 0 \
+                    "Setup GRUB fips configuration"
+            fi
+            ;;
+        ia64)
+            bootconf="/etc/elilo.conf"
+            rlRun "sed -i $sed_options 's/fips=[01] boot=$boot_dev/ /g' $bootconf" 0
+            if grep -q 'append' $bootconf; then
+                rlRun "sed -i $sed_options 's|\(append=.*\)\"|\1 fips=1 boot=$boot_dev\"|g' $bootconf" 0 \
+                    "Reset elilo fips configuration"
+            else
+                rlRun "sed -i $sed_options 's|\(initrd.*\)|\1\n\tappend=\"fips=1 boot=$boot_dev\"|g' $bootconf" 0 \
+                    "Setup elilo fips configuration"
+            fi
+            ;;
+        ppc|ppc64|ppc64le)
+            if rpm -qa | grep "grub2-efi"; then
+                bootconf="/boot/efi/EFI/redhat/grub.cfg"
+                rlRun "sed -i $sed_options 's/ fips=[01] boot=$boot_dev/ /g' $bootconf" 0 \
+                    "Reset GRUB fips configuration"
+                rlRun "sed -i $sed_options 's|\(vmlinuz.*\)|\1 fips=1 boot=$boot_dev|g' $bootconf" 0 \
+                    "Setup GRUB fips configuration"
+            elif rpm -qa | grep "grub2"; then
+                bootconf="/boot/grub2/grub.cfg"
+                rlRun "sed -i $sed_options 's/ fips=[01] boot=$boot_dev/ /g' $bootconf" 0 \
+                    "Reset GRUB fips configuration"
+                rlRun "sed -i $sed_options 's|\(vmlinuz.*\)|\1 fips=1 boot=$boot_dev|g' $bootconf" 0 \
+                    "Setup GRUB fips configuration"
+            else
+                bootconf="/etc/yaboot.conf"
+                grep -q 'append' $bootconf || \
+                    rlRun "sed -i $sed_options 's|\(root=.*\)|\1 append=\"\"|g' $bootconf"
+                rlRun "sed -i $sed_options 's/fips=[01] boot=$boot_dev/ /g' $bootconf" 0 \
+                    "Reset yaboot configuration"
+                rlRun "sed -i $sed_options 's|\(append=.*\)\"|\1 fips=1 boot=$boot_dev\"|g' $bootconf" 0 \
+                    "Setup yaboot configuration"
+            fi
+            ;;
+        s390x)
+            bootconf="/etc/zipl.conf"
+            rlRun "sed -i $sed_options 's/ fips=[01] boot=$boot_dev/ /g' $bootconf" 0 \
+                    "Reset zipl configuration"
+            rlRun "sed -i $sed_options 's/parameters=\"\(.*\)\"/parameters=\"\1 fips=1 boot=$boot_dev\"/g' $bootconf" 0 \
+                    "Setup zipl configuration"
+            rlRun "zipl" 0 "Apply zipl configuration"
+            ;;
+    esac
+}
 
-=cut
 
 # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-#   Functions
+#   Functions and Variables
 # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 true <<'=cut'
 =pod
 
+=head1 VARIABLES
+
+=head2 fipsMode
+
+This variable holds state of FIPS mode at the time when library is loaded.
+
+=over
+
+=back
+
 =head1 FUNCTIONS
 
 =head2 fipsIsEnabled
 
-Function check current state of FIPS mode. Returns 0 if it is correctly 
+Function check current state of FIPS 140 mode. Returns 0 if it is correctly
 enabled, 1 if disabled and 2 otherwise (misconfiguration).
 
 =over
@@ -87,7 +288,10 @@ enabled, 1 if disabled and 2 otherwise (misconfiguration).
 =cut
 
 function fipsIsEnabled {
-    rlLog "Checking FIPS mode status"
+
+    rlLog "Checking FIPS 140 mode status"
+
+    # Check OpenSSL setting.
     if rlIsRHEL '>6.5'; then
         if [[ -n $OPENSSL_ENFORCE_MODULUS_BITS ]]; then
             rlLog "OpenSSL working in new FIPS mode, 1024 bit RSA disallowed!"
@@ -95,30 +299,69 @@ function fipsIsEnabled {
             rlLog "OpenSSL working in compatibility FIPS mode, 1024 bit allowed"
         fi
     fi
-    if grep -q 1 /proc/sys/crypto/fips_enabled; then
-        if rlIsRHEL 4 5 || rlIsRHEL '<6.5'; then
+
+    # Check kernelspace FIPS mode.
+    local kernelspace_fips=$(cat /proc/sys/crypto/fips_enabled)
+
+    # Check userspace FIPS mode.
+    local userspace_fips=$(test -e /etc/system-fips && echo 1 || echo 0)
+
+    # Check crypto policy.
+    local cryptopolicy_fips=$(rlIsRHEL "<8" || update-crypto-policies --show)
+
+    # Check crypto policy.
+    local check_fips=$(rlIsRHEL "<8" || fips-mode-setup --check | grep "FIPS mode")
+
+    # Check FIPS mode.
+    if rlIsRHEL ">=5" && rlIsRHEL "<6.4"; then
+
+        # In RHEL-5 and before RHEL-6.5, only kernel needs to be in FIPS mode.
+        if [ "$kernelspace_fips" == "1" ]; then
             rlLog "FIPS mode is enabled"
             return 0
         else
-            if [ -e /etc/system-fips ]; then
-                rlLog "FIPS mode is enabled"
-                return 0
-            else
-                rlLog "FIPS mode is misconfigured"
-                rlLog "  (kernel flag fips=1 set, but /etc/system-fips is missing)"
-                return 2
-            fi
+            rlLog "FIPS mode is disabled"
+            return 1
         fi
-    else
-        if [ -e /etc/system-fips ]; then
-            rlLog "FIPS mode is misconfigured"
-            rlLog "  (kernel flag fips=0 set, but /etc/system-fips is present)"
-            return 2
-        else
+
+    elif rlIsRHEL ">=6.5" && rlIsRHEL "<8"; then
+
+        # Since RHEL-6.5 and before RHEL-8.0, both userspace and
+        # kernelspace need to be in FIPS mode.
+        if [ "$kernelspace_fips" == "1" ] && [ "$userspace_fips" == "1" ]; then
+            rlLog "FIPS mode is enabled"
+            return 0
+        elif [ "$kernelspace_fips" == "0" ] && [ "$userspace_fips" == "0" ]; then
             rlLog "FIPS mode is disabled"
             return 1
         fi
+
+    elif ! rlIsRHEL "<8"; then
+
+        # Since RHEL-8.0, both userspace and kernelspace need to be
+        # in FIPS mode and FIPS crypto policy must be set, also
+        # fips-mode-setup --check should report that enabling was
+        # completed.
+        if [ "$kernelspace_fips" == "1" ] && \
+           [ "$userspace_fips" == "1" ]   && \
+           [ "$cryptopolicy_fips" == "FIPS" ] && \
+           [ "$check_fips" == "FIPS mode is enabled." ] ; then
+            rlLog "FIPS mode is enabled"
+            return 0
+        elif [ "$kernelspace_fips" == "0" ] && \
+             [ "$userspace_fips" == "0" ]   && \
+             [ "$cryptopolicy_fips" != "FIPS" ] && \
+             [ "$check_fips" == "FIPS mode is disabled." ] ; then
+            rlLog "FIPS mode is disabled"
+            return 1;
+        fi
     fi
+
+    rlLog "FIPS mode is not correctly enabled!"
+    rlLog "kernelspace fips mode = $kernelspace_fips"
+    rlLog "userspace fips mode = $userspace_fips"
+    rlIsRHEL "<8" || rlLog "crypto policy = $cryptopolicy_fips"
+    rlIsRHEL "<8" || rlLog "fips-mode-setup --check = $check_fips"
     return 2
 }
 
@@ -138,41 +381,42 @@ Returns 0 if FIPS mode is supported, 1 if not.
 
 function fipsIsSupported {
 
-    local ARCH=`uname -i`
-    local VER=`cat /etc/redhat-release | sed -n 's/.*\([0-9]\.[0-9]*\).*/\1/p'`
-    local KERNEL=`uname -r | cut -d '.' -f 1`
-    local PASS=0
-
-    rlPhaseStartSetup "Checking FIPS support"
+    local arch=$(uname -i)
+    local rhel=$(cat /etc/redhat-release | sed -n 's/.*\([0-9]\.[0-9]*\).*/\1/p')
+    local kernel=$(uname -r)
+    local supported=1
 
-        if [ `rlGetDistroRelease` -eq "7" ] && [ "$KERNEL" -eq "4" ]; then
-            rlLog "Product: RHEL-ALT-$VER"
-            PASS=1
-        else
-            rlLog "Product: RHEL-$VER"
-        fi
-
-        rlLog "Architecture: $ARCH"
-
-        # FIPS is not allowed on s390x on RHEL <7.1.
-        if [[ $ARCH =~ s390 ]] && rlIsRHEL '<7.1'; then
-            PASS=1
-        fi
-
-        # FIPS is not allowed on AArch64.
-        if [[ $ARCH =~ aarch ]]; then
-            PASS=1
-        fi
+    rlLog "Checking FIPS 140 support"
 
-        if [ "$PASS" -eq "1" ]; then
-            rlLog "FIPS mode is not supported"
-            return 1
-        fi
+    # Check RHEL version.
+    if [[ $rhel =~ 7\. ]] && [[ $kernel =~ ^4\. ]]; then
+        rlLog "Product: RHEL-ALT-7"
+        rlLog "FIPS 140 is not supported in RHEL-ALT-7!"
+        supported=0
+    else
+        rlLog "Product: RHEL-${rhel}"
+    fi
 
-        rlLog "FIPS mode is supported"
-        return 0
+    # Check HW architecture.
+    rlLog "Architecture: $arch"
+    if [[ $arch =~ i[36]86 ]] && ! grep -q "sse2" /proc/cpuinfo; then
+        rlLog "FIPS 140 requires SSE2 instruction set for OpenSSL on Intel!"
+        supported=0
+    elif [[ $arch =~ s390 ]] && rlIsRHEL '<7.1'; then
+        rlLog "FIPS 140 is not supported on s390x in RHEL older than 7.1!"
+        supported=0
+    elif [[ $ARCH =~ aarch ]] && ! rlIsRHEL '8'; then
+        rlLog "FIPS 140 is not supported on aarch64 in RHEL older than 8.0!"
+        supported=0
+    fi
 
-    rlPhaseEnd
+    # Report,
+    if [ "$supported" == "0" ]; then
+        rlLog "FIPS 140 mode is not supported"
+        return 1
+    fi
+    rlLog "FIPS 140 mode is supported"
+    return 0
 }
 
 true <<'=cut'
@@ -180,237 +424,74 @@ true <<'=cut'
 
 =head2 fipsEnable
 
-Function enables FIPS 140 product, please notice that the process includes 
-inevitable restart of the machine. Returns 0 if FIPS mode was correctly enabled,
-1 if not and 2 in case that any error was encountered.
+Function enables FIPS 140 mode. Enablement must be completed by system restart.
+Returns 0 if enabling was successful, 1 otherwise.
 
 =over
 
 =back
 
 =cut
-
 function fipsEnable {
 
-    local ARCH=`uname -i`
-
-    rlPhaseStartSetup "Enable FIPS mode"
-    
-    # FIPS requires SSE2 instruction set for OpenSSL.
-    if  echo $ARCH | grep "i[36]86" && ! grep "sse2" /proc/cpuinfo; then
-        rlLogError "FIPS requires SSE2 instruction set for OpenSSL";
-        return 1
-    fi
-    
-    # FIPS must be supported before its enabling.
-    if ! rlRun "fipsIsSupported"; then
-        return 1
-    fi
+    rlLog "Enabling FIPS 140 mode"
 
-    # Verify the FIPS state.
-    if grep "1" "/proc/sys/crypto/fips_enabled"; then
-        if rlIsRHEL ">=6" && !rlCheckRpm "dracut-fips"; then
-            continue;
-        fi
-        rlLog "FIPS is already enabled!"
-    fi
-    
-    # Backup a message of the day.
-    rlRun "cp -f /etc/motd /var/tmp/motd.backup" 0
-    
     # Turn-off prelink (if prelink is installed).
-    if rlCheckRpm "prelink"; then
-        # sometimes prelink complains about files being changed during
-        # unlinking so let's run a simple yum command to make sure yum
-        # is not running in the background ("somehow") and wait for it
-        # to finish (yum automatically uses lockfiles for that)
-        if ! rlIsRHEL '<5'; then
-            rlRun "yum list --showduplicates prelink"
-        fi
-        
-        # make sure prelink job is not running now (e.g. started by cron)
-        rlRun "killall prelink" 0,1
-        rlRun "sed -i 's/PRELINKING=.*/PRELINKING=no/g' /etc/sysconfig/prelink" 0
-        rlRun "sync" 0 "Commit change to disk"
-        rlRun "killall prelink" 0,1
-        rlRun "prelink -u -a" 0
-    fi
-    
-    # Enforce 2048 bit limit on RSA and DSA generation (RHBZ#1039105)
-    if ! rlIsRHEL '<6.5' 5 4; then
-        if ! grep 'OPENSSL_ENFORCE_MODULUS_BITS' /etc/environment; then
-            rlRun "echo 'OPENSSL_ENFORCE_MODULUS_BITS=true' >> /etc/environment"
-        fi
-        rlRun "echo 'export OPENSSL_ENFORCE_MODULUS_BITS=true' > /etc/profile.d/openssl.sh"
-        rlRun "chmod +x /etc/profile.d/openssl.sh"
-        rlRun "echo 'setenv OPENSSL_ENFORCE_MODULUS_BITS true' > /etc/profile.d/openssl.csh"
-        rlRun "chmod +x /etc/profile.d/openssl.csh"
-        # beaker tests don't use profile or environment so we have to set
-        # their environment separately
-        BEAKERLIB=${BEAKERLIB:-"/usr/share/beakerlib"}
-        rlRun "mkdir -p '${BEAKERLIB}/plugins/'" 0-255
-        rlRun "echo 'export OPENSSL_ENFORCE_MODULUS_BITS=true' > '${BEAKERLIB}/plugins/openssl-fips-override.sh'"
-        rlRun "chmod +x '${BEAKERLIB}/plugins/openssl-fips-override.sh'"
-    fi
-    
-    if ! rlIsRHEL 5; then
-        
-        # Install dracut and dracut-fips on RHEL7 and RHEL6
-        rlCheckRpm "dracut" || rlRun "yum --enablerepo='*' install dracut -y" 0
-        rlCheckRpm "dracut-fips" || rlRun "yum --enablerepo='*' install dracut-fips -y" 0
-        if grep -sE '\<aes\>' /proc/cpuinfo && grep -sE '\<GenuineIntel\>' /proc/cpuinfo; then
-            rlLogInfo "AES instruction set on Intel CPU detected"
-            rlCheckRpm "dracut-fips-aesni" || \
-                rlRun "yum --enablerepo='*' install -y dracut-fips-aesni" 0 \
-                "Installing dracut-fips-aesni"
-                
-        else
-            rlLogInfo "CPU is a non-Intel or lacking AES instruction set"
-            rlCheckRpm "dracut-fips-aesni" && \
-                rlRun "yum remove -y dracut-fips-aesni" 0 "Removing dracut-fips-aesni"
-        fi
-
-        # Re-generate initramfs to include FIPS integrity checks.
-        rlLogInfo "Regenerating initramfs"
-        rlRun "dracut -v -f" 0
-    fi
-    
-    
-    return 2
-}
+    _disablePrelink || return 1
 
+    # Enforce 2048 bit limit on RSA and DSA generation (RHBZ#1039105).
+    _enforceModulusBits || return 1
 
-function _modifyBootLoader {
+    # Workarounds for testing in FIPS 140 mode.
+    _workarounds || return 1
 
-    local ARCH=`uname -i`
+    # Enable FIPS 140 mode.
+    _enableFIPS || return 1
 
-    # Fine-tune SED options
-    if rlIsRHEL 5; then
-        SED_OPTIONS='-c'
-    else
-        SED_OPTIONS='--follow-symlinks'
-    fi
-    
-    # Remove any FIPS-related kernel parameters first
-    sed -i $SED_OPTIONS 's/ fips=[01] boot=$fipsBOOTDEV/ /g' $fipsBOOTCONF
-    sed -i $SED_OPTIONS 's/ fips=[01] boot=$fipsBOOTDEV/ /g' $fipsBOOTCONF
+    # Modify bootloader.
+    _modifyBootloader || return 1
 
-    case $ARCH in
-        i386|x86_64)
-            if rlCheckRpm "grub2" || rlCheckRpm "grub2-efi"; then
-                rlRun "sed -i $SED_OPTIONS 's|\(vmlinuz.*\)|\1 fips=1 boot=$BOOT_DEV|g' $BOOTCONF"
-            else
-                rlRun "sed -i $SED_OPTIONS 's|\(kernel.*\)|\1 fips=1 boot=$BOOT_DEV|g' $BOOTCONF" 0
-            fi
-            ;;
-        ia64)
-            if grep -q 'append' $BOOTCONF; then
-                rlRun "sed -i $SED_OPTIONS 's|\(append=.*\)\"|\1 fips=1 boot=$BOOT_DEV\"|g' $BOOTCONF" 0
-            else
-                rlRun "sed -i $SED_OPTIONS 's|\(initrd.*\)|\1\n\tappend=\"fips=1 boot=$BOOT_DEV\"|g' $BOOTCONF" 0
-            fi
-            ;;
-        ppc|ppc64|ppc64le)
-            if rlCheckRpm "grub2" || rlCheckRpm "grub2-efi"; then
-                rlRun "sed -i $SED_OPTIONS 's|\(vmlinuz.*\)|\1 fips=1 boot=$BOOT_DEV|g' $BOOTCONF"
-            else
-                if grep -q 'append' $BOOTCONF; then
-                    rlRun "sed -i $SED_OPTIONS 's|\(append=.*\)\"|\1 fips=1 boot=$BOOT_DEV\"|g' $BOOTCONF" 0
-                else
-                    rlRun "sed -i $SED_OPTIONS 's|\(root=.*\)|\1 append=\"\"|g' $BOOTCONF"
-                fi
-            fi
-            ;;
-        s390x)
-            rlRun "sed -i $SED_OPTIONS 's/parameters=\"\(.*\)\"/parameters=\"\1 fips=1 boot=$BOOT_DEV\"/g' $BOOTCONF" 0
-	    rlRun "zipl" 0
-            ;;
-        
-    esac	    
+    # Success.
+    return 0
 }
 
-function fipsSetState {
-    
-    local new_state=$1
-
-    case "$new_state" in
-        0)
-           ;; 
-        *)
-            rlLogError "Unexpected state (\"$new_state\" given, 0-3 expected)"
-    esac
-    
-    return 2
-}
 
 true <<'=cut'
 =pod
 
-=head2 fipsDisable
+=head2 fipsLibraryLoaded
 
-Function disables FIPS 140 product, please notice that the process includes 
-inevitable restart of the machine. Returns 0 if FIPS mode was correctly disabled,
-1 if not and 2 in case that any error was encountered.
+Initialization callback.
+Importing this library with misconfigured (neither fully disabled nor
+fully enabled) FIPS 140 mode will produce an error.
 
 =over
 
 =back
 
 =cut
+function fipsLibraryLoaded {
 
-function fipsDisable {
-    return 2
-}
-
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-#   Initialization & Verification 
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-#
-#   This is an initialization and verification callback which will be 
-#   called by rlImport after sourcing the library. The function
-#   returns 0 only when the library is ready to serve.
-
-fipsLibraryLoaded() {
-
-    fipsBOOTDEV=`df -P /boot/ | tail -1 | awk '{print $1}'`
-    if [ -z "$fipsBOOTDEV" ]; then
-        rlLogError "Unable to detect /boot device name!"
-
-        # debug
-        df /boot/
-
-        return 1
-    fi
+    _fipsLIBDIR="/mnt/tests/distribution/Library/fips/"
 
-    if [[ "${USE_UUID:-yes}" != "no" && "${USE_UUID:-1}" != "0" ]]; then
-        
-        UUID=$(blkid -s UUID -o value $fipsBOOTDEV)
-        if [ -z "$UUID" ]; then
-            rlLogError "Unable to detect boot device UUID!"
-                
-            # debug
-            df /boot
-            blkid -s UUID -o value $fipsBOOTDEV
-            
-            return 1
-        fi
-        
-        fipsBOOTDEV="UUID=$UUID"               
+    # In Fedora, fips-mode-setup is separate package, but cannot 
+    # be installed via fips library dependecies.
+    if rlIsFedora && ! which fips-mode-setup >/dev/null 2>&1; then
+        rlLog "Installing Missing fips-mode-setup package"
+        rlRun "dnf install fips-mode-setup -y" 
     fi
     
-    fipsBOOTCONFIG="/boot/grub2/grub.cfg"
-    case "$(uname -i)" in
-        i386|x86_64)
-            rlCheckRpm "grub2" || fipsBOOTCONFIG="/boot/grub/grub.conf"
-            ;;
-        ia64)
-            fipsBOOTCONFIG="/etc/elilo.conf"
-            ;;
-        ppc|ppc64)
-            rlCheckRpm "grub2" || fipsBOOTCONFIG="/boot/etc/yaboot.conf"
-            ;;
-    esac            
-    rlLog "Setting fipsBOOTCONFIG=$fipsBOOTCONFIG"
+    fipsIsEnabled 
+    ret=$?
+    
+    if [ $ret == 0 ]; then
+        fipsMode="enabled"
+    elif [ $ret == 1 ]; then
+        fipsMode="disabled"
+    else
+        fipsMode="error"
+        rlFail "FIPS mode is already misconfigured, see above!"
+    fi
 
     return 0
 }
@@ -433,4 +514,3 @@ Ondrej Moris <omoris@redhat.com>
 =back
 
 =cut
-
diff --git a/distribution/fips/rstrnt-package-workaround.sh b/distribution/fips/rstrnt-package-workaround.sh
new file mode 100644
index 0000000..a8594d8
--- /dev/null
+++ b/distribution/fips/rstrnt-package-workaround.sh
@@ -0,0 +1,22 @@
+#!/bin/bash
+
+tmp_dir=$(mktemp -d)
+
+shift
+operation=$1
+shift 
+packages=$*
+
+if [[ "$operation" == "remove" ]]; then
+
+    dnf remove -y $packages
+    
+elif [[ "$operation" == "install" ]]; then
+
+    pushd $tmp_dir 
+    dnf install --downloadonly -y --downloaddir . --skip-broken $packages
+    rpm -Uhv --nodigest --nofiledigest --nodeps *.rpm
+    popd
+fi
+
+rm -rf $tmp_dir
diff --git a/distribution/fips/runtest.sh b/distribution/fips/runtest.sh
index 0d810d9..7c99e77 100755
--- a/distribution/fips/runtest.sh
+++ b/distribution/fips/runtest.sh
@@ -3,12 +3,12 @@
 # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 #
 #   runtest.sh of /distribution/Library/fips
-#   Description: A set of helpers for FIPS related testing.
+#   Description: A set of helpers for FIPS 140 testing.
 #   Author: Ondrej Moris <omoris@redhat.com>
 #
 # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 #
-#   Copyright (c) 2012 Red Hat, Inc. All rights reserved.
+#   Copyright (c) 2018 Red Hat, Inc. All rights reserved.
 #
 #   This copyrighted material is made available to anyone wishing
 #   to use, modify, copy, or redistribute it subject to the terms
@@ -27,23 +27,47 @@
 # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 # Include Beaker environment
-[ -e /usr/bin/rhts-environment.sh ] && . /usr/bin/rhts-environment.sh
+[ -e /usr/bin/rhts-environment.sh ] && . /usr/bin/rhts-evironment.sh
 . /usr/share/beakerlib/beakerlib.sh || exit 1
 
-PHASE=${PHASE:-Test}
-
 rlJournalStart
     rlPhaseStartSetup
-        rlRun "rlImport distribution/fips"
+        rlRun "rlImport distribution/fips" || rlDie
     rlPhaseEnd
 
-    # Self test
-    if [[ "$PHASE" =~ "Test" ]]; then
+    if ! [ -e /var/tmp/fips-reboot ]; then
         rlPhaseStartTest
-          rlRun "fipsIsEnabled" 0	     
-       rlPhaseEnd
-    fi
 
+            # Check that FIPS 140 mode is supported.
+            rlRun "fipsIsSupported" 0,1
+            if [ $? -eq 0 ]; then
+
+                # Initially, FIPS mode is disabled.
+                rlRun "fipsIsEnabled" 1
+                
+                # Enable it.
+                rlRun "fipsEnable" 0
+                
+                # Before completing setup by restart, system is misconfigured.
+                rlIsRHEL ">6.5" && rlRun "fipsIsEnabled" 2
+                
+                rlRun "touch /var/tmp/fips-reboot" 0
+                
+            rlPhaseEnd
+
+            rhts-reboot
+            fi
+    else
+        rlPhaseStartTest
+
+            # Now, FIPS mode is enabled.
+            rlRun "fipsIsEnabled" 0
+
+            rlRun "rm -f /var/tmp/fips-reboot" 0
+
+        rlPhaseEnd
+    fi
+    
     rlPhaseStartCleanup
     rlPhaseEnd
 rlJournalPrintText

