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.
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
An example of changing behaviour can be found in this pull request.
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
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.