Preparing Local Plug-ins for FIPS Compliance

vSphere Client 7.0 U2 | 9 March 2021 | ESXi build 17630552, vCenter build 17694817
For vSphere 7.0 Update 2 | Last document update 20 September 2021
If these instructions change, additions or updates will be marked New.

In a future release of vSphere, VMware will require all vSphere Client local plug-ins, both partner-supplied and VMware-supplied, to comply with the United States government Federal Information Processing Standard (FIPS) Publication 140-2, Level 1, Security Requirements for Cryptographic Modules. That standard assures up-to-date data communication security by mandating the use of highly secure encryption algorithms.

This document explains how you can upgrade your plug-in to use conformant encryption libraries correctly for interprocess communications.  The instructions assume the use of Bouncy Castle FIPS libraries. By coding your plug-in to use default encryption providers, you enable your code to operate either with standard JVM encryption or with Bouncy Castle FIPS encryption.

NOTE: The FIPS security requirement will not take effect in the vSphere 7.0 release generation. However, you will be able to configure vCenter Server to operate with or without FIPS providers in these releases. VMware is already upgrading its internal plug-ins, and we recommend that partners act soon to upgrade and test their own plug-ins with the new libraries.

Check Recommendation

Check whether Bouncy Castle is directly in use in your source code. Look for a library import such as 

org.bouncycastle

If Bouncy Castle is directly in use, refactor the code to use the Bouncy Castle FIPS distribution instead. The recommended versions of the Bouncy Castle FIPS libraries are:

  • bc-fips 1.0.2
  • bcpkix-fips 1.0.4

Refactor the code according to the Bouncy Castle FIPS best practices. The official user guide and examples are publicly available:

Check the usages of

 SecureRandom.getInstance(<algorithm>)
Use the default constructor for creation of new SecureRandom instances. This will imply the usage of the FIPS compliant algorithms provided by the Bouncy Castle Security providers.

Check the usages of

 KeyStore.getInstance("JKS")
  1. Use the default type when creating new instances:
    KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
  2. Use two null parameters when loading the keystore: 
    trustStore.load(null, null);
  3. The Bouncy Castle keystore format (BCFKS) is incompatible with the JKS keystore format. Do not try to mix both types.

Check the usages of

 KeyPairGenerator.getInstance

If you have:

 KeyPairGenerator.getInstance("RSA", <specific-provider>)

then remove the <specific-provider> reference.

The recommended way to get a new instance is:

 KeyPairGenerator.getInstance("RSA")
Check if MD5 algorithms used for security reasons. Replace MD5 with a SHA-256 or stronger algorithm.
Check if SHA-1 is used for a reason other than just a certificate validation. Replace SHA-1 with SHA-256 or stronger.

Check if your plugin makes outbound connections over HTTPS, or other protocol that requires TLS.

Test to be sure the plugin works with Bouncy Castle TLS.

The following code example shows how to do this:

 SSLContext ctx = SSLContext.getInstance("TLS");
 ctx.init(...);
The Bouncy Castle implementation requires the SSLContext::init call immediately after the instance is created. Any operation between the instance creation and SSLContext::init call is expected to fail.
Check whether public/private key ciphers are in use. You can search for Cipher.getInstance.

If you find

 Cipher.getInstance("RSA...

or

 Cipher.getInstance("ELGAMAL...

please make sure that you use them explicitly in WRAP_MODE/UNWRAP_MODE.

For example:

 cipher.init(Cipher.WRAP_MODE, x509crt.getPublicKey());
Check whether the plug-in implements a HostnameVerifier. New

Plug-ins are required to implement a custom HostnameVerifier when establishing a connection to a vCenter Server (for example, when using the vSphere Web Services API).

To implement a HostnameVerifier, consult the advice below this table.

 

Implement a HostnameVerifier New

The following example code outlines the basic components needed to implement a HostnameVerifer routine. The plug-in developer is responsible for implementing a HostnameVerifier consistent with security best practices.

  1. Store the vCenter Server thumbprint in a thread-safe collection before calling the Web Services API.

    For example:

        
    String thumbprint = serverInfo.thumbprint.replaceAll(":", "").toLowerCase();      
    ThumbprintTrustManager.addThumbprint(thumbprint);
    ServiceContent serviceContent = _vimPort.retrieveServiceContent(serviceInstanceRef);
        
        
  2. Add a method to check that the thumbprint is in the list of trusted thumbprints.

    For example:

        
    public static void checkThumbprint(X509Certificate cert) throws CertificateException {
      String thumbprint = getThumbprint(cert);
      if(!_thumbprints.contains(thumbprint)) {
        _logger.error(ERROR_MSG);
        throw new CertificateException(ERROR_MSG);
      }
    }
        
        
  3. Invoke the thumbprint check with a custom HostnameVerifier in your plug-in request handler chain.

    For example:

        
    reqContext.put("com.sun.xml.internal.ws.transport.https.client.hostname.verifier",
                   new HostnameVerifier() {
      @Override
      public boolean verify(String s, SSLSession sslSession) {
        try {
          Certificate[] certificates = sslSession.getPeerCertificates();
          ThumbprintTrustManager.checkThumbprint((X509Certificate) certificates[0]);
        } catch (SSLPeerUnverifiedException | CertificateException e) {
          return false;
        }
          return true;
        }
      }
    );
        
        

Copyright © 2021 VMware, Inc. All rights reserved.