FIPS-140 for developers

This site is the new docs site currently being tested. For the actual docs in use please go to https://www.jenkins.io/doc.

This section is a work in progress. Want to help? Check out the jenkinsci/docs gitter channel. For other ways to contribute to the Jenkins project, see this page about participating and contributing.

In order for the code in Jenkins and plugins to be compliant with FIPS-140, sensitive information needs to be handled correctly. This document provides a non-exhaustive cheat sheet that can guide developers to write code that is FIPS-140 compliant. This applies to all forms of cryptography, regardless if it is encryption/decryption, hashing, or signing.

FIPS-140 compliant code may result in less security as the approved standards can lag behind more secure modern standards. Your plugin and Jenkins code should not automatically follow the tips here, but may also need to make decisions at runtime whether or not to use a FIPS-140 compliant option.

Any sensitive information for accessing an external system that is persisted should be stored either as a hudson.util.Secret or a com.cloudbees.plugins.credentials.Credentials

Rely only on Java Cryptography Architecture (JCA) or BouncyCastle via the BouncyCastle API plugin when performing cryptography. Do not depend on any third-party libraries or write your own code to perform encryption or specify any specific java.security.Provider when obtaining a concrete JCA implementation. Additionally, the subset of algorithms that are used should be restricted to the subset that is supported by the BouncyCastle FIPS implementation.

FIPS-140 has no support for asymmetric encryption such as RSA.

If there is a tradeoff made between FIPS-140 support or a more secure option, the tradeoff should be made at runtime by checking jenkins.security.FIPS140.useCompliantAlgorithms. An example of changing behaviour can be found in this pull request.

If using a java.security.SecureRandom it should be obtained via new SecureRandom() or SecureRandom.getInstanceStrong(). Do not use any of the methods or constructors that take an optional seed.

Jenkins core may provide some libraries that are not FIPS-140 compliant for some API calls, but the specific calls that Jenkins makes to these libraries are compliant. Therefore it is important that this guidance is applied to all libraries used by your your plugin, regardless of if it is bundled in the plugin or comes from a transitive dependency such as Jenkins core or another plugin.

Care must be taken when obtaining / creating a java.security.KeyStore. The majority of Keystores provided by stock JDKs are not FIPS-140 compliant and the one that is can not be used to store keys only certificates. A FIPS-140 compliant KeyStore provider would need to be provided by the JVM, as the name of this can not be known at compile time, any code that requires to create a keystore should assume that this has been configured as the default type and use KeyStore.getInstance(KeyStore.getDefaultType()) to obtain an new instance.