[PATCH RFC 103/104] Documentation/crypto: add fips140.rst

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Add documentation for the FIPS140 standalone module.

Cc: Jonathan Corbet <corbet@xxxxxxx>
Cc: linux-doc@xxxxxxxxxxxxxxx
Signed-off-by: Vegard Nossum <vegard.nossum@xxxxxxxxxx>
---
 Documentation/crypto/fips140.rst | 231 +++++++++++++++++++++++++++++++
 Documentation/crypto/index.rst   |   1 +
 2 files changed, 232 insertions(+)
 create mode 100644 Documentation/crypto/fips140.rst

diff --git a/Documentation/crypto/fips140.rst b/Documentation/crypto/fips140.rst
new file mode 100644
index 000000000000..14a7fb7a69ed
--- /dev/null
+++ b/Documentation/crypto/fips140.rst
@@ -0,0 +1,231 @@
+=========================
+FIPS140 standalone module
+=========================
+
+:Author: Vegard Nossum <vegard.nossum@xxxxxxxxxx>
+
+
+Target audience
+===============
+
+This document is primarily meant for Linux distribution developers and
+maintainers. It may also be interesting for kernel developers
+contributing to the kernel's crypto code as it explains some of the
+concepts and rationale behind the architecture of the crypto code and
+how FIPS support is implemented.
+
+
+Introduction
+============
+
+FIPS 140-3 is a Federal Information Protection Standard, "Security
+Requirements for Cryptographic Modules", maintained by the US National
+Institute of Standards and Technology (NIST). [#fips140]_
+
+Binary implementation of specific approved cryptographic algorithms
+can be certified as part of the Cryptographic Module Validation
+Program (CMVP). In practice, the certification process includes both
+source and binary code, though the end result is a certification
+attached to the binary code.
+
+Having FIPS 140-3 certification is a requirement for running in many
+secure contexts -- many Linux distros certify their kernels in order
+to satisfy these requirements.
+
+Many distros have certified the entire kernel as a "FIPS module" (not
+to be confused with kernel modules). Unfortunately, this means that
+one cannot change any part of the kernel without invalidating the
+certification. Moreover, certification is a costly process that can
+last up to or even more than 12 months.
+
+The FIPS 140 standalone module (AKA ``fips140.ko``) fixes this situation
+by allowing one to build the kernel's crypto code once and reuse it in
+subsequent builds, thus enabling the rest of the kernel to receive bug
+fixes and updates without invalidating the certification of the FIPS
+module.
+
+
+Design
+======
+
+Requirements:
+
+- the FIPS module must not impose a stable internal kernel API on
+  mainline or stable kernels
+- the FIPS module must be a single, contiguous binary file and its HMAC
+  (for easy verification)
+- all crypto algorithms and code must reside within the FIPS module
+- no crypto code in the FIPS module can be used before the FIPS module
+  has executed its self-tests
+- the FIPS module only comes into play when the kernel is booted with
+  ``fips=1``
+- source code should be shared between the kernel and the FIPS module
+  where possible
+
+In order to satisfy these requirements, we have settled on a design
+where the FIPS module duplicates the crypto API and all the algorithm
+implementations that are part of the FIPS module. To avoid source code
+duplication, we use symlinks from ``fips140/`` to the rest of the kernel
+tree and build this directory as an external module -- in other words,
+all the code and algorithms is built twice; once as part of vmlinux
+and/or regular (non-FIPS) kernel modules, and once as part of
+``fips140.ko``.
+
+To allow hot-swapping the crypto code (API + algorithms) at runtime
+(i.e. when ``fips=1`` is detected during boot), we wrap any exported
+symbols in C macros. These macros use static calls (see [#static_call]_)
+to patch any and all users of the crypto code to call the FIPS module's
+version of these functions instead of the functions in vmlinux.
+
+``fips140.ko`` is not really an ordinary kernel module -- it is not
+meant to be loaded with ``modprobe`` or ``insmod``; instead, it is
+embedded into the ``vmlinux`` image at build time. This avoid any
+chicken-and-egg issues around how to verify cryptographic signatures
+without using unverified crypto code. ``fips140.ko`` is loaded during
+early boot -- before any crypto code is used by the kernel.
+
+The code for the FIPS 140 standalone module is therefore split into
+two parts: the module itself (``fips140.ko``) and the loader
+(``crypto/fips140-loader.c``). The loader is **NOT** part of the module
+itself and is not covered by the certification; however, it is
+essentially just a wrapper around the kernel module loader that runs
+during early boot.
+
+We provide no explicit mechanisms to ensure compatibility between a
+precompiled FIPS module and the rest of the kernel; this is the
+responsibility of distros that choose to use the standalone FIPS module.
+
+
+Building
+========
+
+First off, ensure that ``CONFIG_CRYPTO_FIPS140_EXTMOD`` is enabled.
+
+Prepare for building out-of-tree module::
+
+  make modules_prepare
+
+Build fips140.ko as an out-of-tree module::
+
+  make M=fips140/ KBUILD_MODPOST_WARN=1
+  cp fips140/fips140.ko crypto/
+
+Generate fips140.hmac::
+
+  hmac_key=$(awk -F'"' '/^CONFIG_CRYPTO_FIPS140_HMAC_KEY=/{print $2}' .config)
+  openssl dgst -sha256 -hmac $hmac_key -binary -out crypto/fips140.hmac crypto/fips140.ko
+
+Build the rest of the kernel::
+
+  make
+
+
+Adopting a standaline FIPS module for your distro
+=================================================
+
+1. Carefully select which algorithms you want your FIPS module to
+   provide (``CONFIG_FIPS140_*`` and ``CONFIG_CRYPTO_FIPS140_*``
+   options)
+
+2. Integrate building ``fips140/`` as an out-of-tree module with the
+   build system used by your distro's package manager.
+
+   - You may want to strip and separate out debuginfo before copying
+     ``fips140.ko`` into ``crypto/``.
+   - You need a mechanism to save and reintroduce the precompiled
+     ``fips140.ko`` between builds.
+   - All of this "build support" infrastructure is out of scope for
+     mainline.
+
+3. Verify that the FIPS module satisfies your specific operational
+   requirements.
+
+4. Submit the FIPS module to the certifying lab.
+
+.. warning::
+   Mainline developers cannot and will not assist in getting a specific
+   FIPS module certified. The code provided in the mainline source tree
+   is intended to make certification of standalone FIPS modules easier,
+   but we do not guarantee that a build will be certifiable as-is out of
+   the box. Moreover, different distributions have different use cases,
+   different requirements, etc. and all of this influences the specifics
+   of any given FIPS module. Mainline developers will not be responsible
+   for the certification or certifiability of your FIPS module.
+
+
+Useful commands
+===============
+
+
+Extracting ``fips140.ko`` from ``vmlinux``
+------------------------------------------
+
+To extract ``fips140.ko`` and ``fips140.hmac`` from an existing
+``vmlinux`` build, use::
+
+  $ scripts/extract-fips140 /path/to/vmlinux
+  extracted fips140.ko
+  extracted fips140.hmac
+
+
+Verifying the ``fips140.ko`` HMAC digest
+----------------------------------------
+
+To verify the HMAC digest of ``fips140.ko``, use::
+
+  $ key="Sphinx of black quartz, judge my vow"
+  $ openssl dgst -sha256 -hmac "$key" -binary fips140.ko > fips140.hmac-computed
+  $ cmp -s fips140.hmac fips140.hmac-computed && echo ok
+  ok
+
+
+List the symbols used by ``fips140.ko``
+---------------------------------------
+
+To list the kernel symbols used by ``fips140.ko`` (useful for checking
+whether all the necessary crypto functions have been included in the
+module), use::
+
+  $ nm --undefined-only fips140.ko
+
+
+Quick crypto verification using AF_ALG
+--------------------------------------
+
+Testing whether the code works properly is fairly easy using Python
+and the ``AF_ALG`` interface, e.g.::
+
+  import socket
+
+  ALG_SET_KEY = 1
+
+  s = socket.socket(socket.AF_ALG, socket.SOCK_SEQPACKET, 0)
+  s.bind(('hash', 'hmac(sha256)'))
+  s.setsockopt(socket.SOL_ALG, ALG_SET_KEY, b'x' * 16)
+
+  op, _ = s.accept()
+  op.sendall(b'x' * 32)
+  print(op.recv(32))
+
+
+Tracing the crypto code
+-----------------------
+
+Testing whether the FIPS module is used correctly can also be done
+using a combination of Python (as above) and ``trace-cmd`` like this::
+
+  $ sudo trace-cmd record -p function_graph -g __sys_bind python hmac.py
+  $ trace-cmd report
+
+
+Contributing
+============
+
+Patches welcome.
+
+
+References
+==========
+
+.. [#fips140] <https://csrc.nist.gov/pubs/fips/140-3/final>
+.. [#static_call] <https://lwn.net/Articles/815908/>
diff --git a/Documentation/crypto/index.rst b/Documentation/crypto/index.rst
index 100b47d049c0..e755ffd08d4f 100644
--- a/Documentation/crypto/index.rst
+++ b/Documentation/crypto/index.rst
@@ -27,3 +27,4 @@ for cryptographic use cases, as well as programming examples.
    descore-readme
    device_drivers/index
    krb5
+   fips140
-- 
2.39.3





[Index of Archives]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Big List of Linux Books]

  Powered by Linux