Java

Java

Java

Topics on Semeru (Java) on IBM Z

 View Only

How IBMJCEHYBRID can reduce errors in your Java programs

By Gregory Cernera posted Mon January 30, 2023 01:42 AM

  

What is IBMJCEHYBRID?

IBMJCEHYBRID is an IBM z/OS Java security provider that routes cryptographic application requests to different JCE providers, depending on their availability and capabilities . Many Java security providers rely on cryptographic hardware, facilities, and APIs that operate on the mainframe. These services provide strong & secure cryptographic algorithms, along with faster speed and security than operations performed using software. While these services are reliable and allow many IBM providers to function, they can also be volatile.

In the event that a hardware, API, or service is not configured properly or is temporarily unavailable, this circumstance could cause a security provider that relies on one or more of these services to become disabled and, ultimately, break the Java application. We obviously do not want our applications to break - especially in production. So, how do we address this concern - with IBMJCEHYBRID!

How IBMJCEHYBRID can help your Java apps

IBMJCEHYBRID is designed to provide failover from one JCE provider to the next depending on their current availability. IBMJCEHYBRID does not perform the cryptographic operations itself, but rather routes the operation to its succeeding JCE providers until it can successfully perform the requested function or reach the end of the list. This allows your Java application to take advantage of z/OS cryptographic features when they are available, and be able to failover to use another JCE provider that does not rely on these services in the event they are not available.

What does this mean for your Java applications?

  • There is no longer a single point of failure
  • IBMJCEHYBRID will determine the best provider to use, so you don't have to
  • Your Java applications will continue to run even if the hardware crypto services are not available

How to enable IBMJCEHYBRID

Enabling IBMJCEHYBRID is simple. For this demonstration (and the examples in the following sections), I will be using an IBM Semeru Runtime Certified Edition for z/OS, Version 11 JDK.

To enable IBMJCEHYBRID, you must open the java.security file located in <JAVA_HOME>/lib/security/java.security and edit the security provider list so that IBMJCEHYBRID is the #1 provider in the list (some lines from the java.security file were omitted for conciseness)...

#
# List of providers and their preference orders (see above):
#
security.provider.1=IBMJCEHYBRID
security.provider.2=IBMJCECCA
security.provider.3=OpenJCEPlus
security.provider.4=IBMZSecurity

This will allow Java applications to use IBMJCEHYBRID for all cryptographic requests so that we can have the added benefits discussed in the previous section.

Examples

Now, let's look at two (2) examples: one of a Java application that does not use IBMJCEHYBRID and one that does. I will be using an IBM Semeru Runtime Certified Edition for z/OS, Version 11 JDK.

Sample Java App

For this Java app, we will try to encrypt an AES/GCM/NoPadding Cipher. However, for this example, we will be assuming that ICSF is not started on our mainframe. Here is our Java app that we'll be using...

import java.security.SecureRandom;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.GCMParameterSpec;
import javax.crypto.spec.SecretKeySpec;

public class App {
    public static void main(String[] args) throws Exception {
        String plainText = "Hello from IBM!";
        int AES_KEY_SIZE = 256;
        int GCM_IV_LENGTH = 12;
        int GCM_TAG_LENGTH = 16;

        // Create KeyGenerator object
        KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");

        // Initialize the key pair generator
        keyGenerator.init(AES_KEY_SIZE);

        // Generate the secret key
        SecretKey key = keyGenerator.generateKey();

        // Get a random initialization vector
        byte[] IV = new byte[GCM_IV_LENGTH];
        SecureRandom random = new SecureRandom();
        random.nextBytes(IV);

        // Create a Cipher instance
        Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");

        // Create SecretKeySpec
        SecretKeySpec keySpec = new SecretKeySpec(key.getEncoded(), "AES");

        // Create GCMParameterSpec
        GCMParameterSpec gcmParameterSpec = new GCMParameterSpec(GCM_TAG_LENGTH * 8, IV);

        // Initialize Cipher for ENCRYPT_MODE
        cipher.init(Cipher.ENCRYPT_MODE, keySpec, gcmParameterSpec);

        // Perform Encryption
        byte[] cipherText = cipher.doFinal(plainText.getBytes());

        // Print out the cipher text in hex
        StringBuilder cipherTextHex = new StringBuilder();
        for (byte b : cipherText) {
            cipherTextHex.append(String.format("%02x", b));
        }
        System.out.println("Cipher text: " + cipherTextHex.toString());
    }
}

Example 1: Not using IBMJCEHYBRID

Let's configure our java.security file to not include IBMJCEHYBRID. My java.security file now looks like this...

#
# List of providers and their preference orders (see above):
#
security.provider.1=IBMJCECCA
security.provider.2=OpenJCEPlus
security.provider.3=IBMZSecurity

Remember that ICSF is disabled for this example. Let's see what happens when we try to run our Java app with this provider list...

Exception in thread "main" com.ibm.crypto.hdwrCCA.provider.JCECCARuntimeException: Hardware error from call CSNBSYE RC = 12 RSN = 0
    at ibm.crypto.hdwrcca/com.ibm.crypto.hdwrCCA.provider.JCEHdwrUtils.d(JCEHdwrUtils.java:1947)
    at ibm.crypto.hdwrcca/com.ibm.crypto.hdwrCCA.provider.AESCipher.c(AESCipher.java:2936)
    at ibm.crypto.hdwrcca/com.ibm.crypto.hdwrCCA.provider.AESCipher.b(AESCipher.java:1127)
    at ibm.crypto.hdwrcca/com.ibm.crypto.hdwrCCA.provider.AESCipher.b(AESCipher.java:837)
    at java.base/javax.crypto.Cipher.a(Cipher.java:102)
    at App.main(App.java:44)

Since ICSF is not started and IBMJCECCA is the first provider in our list, our program failed because IBMJCECCA tried to use ICSF to perform the AES/GCM cipher encryption, but was not able to communicate with the ICSF service. IBMJCECCA had no choice but to throw an exception indicating that the cipher could not be performed because the underlying hardware was not available.

Example 2: Using IBMJCEHYBRID

Now, let's try running the exact same testcase but instead we'll have IBMJCEHYBRID at the top of the provider list...

#
# List of providers and their preference orders (see above):
#
security.provider.1=IBMJCEHYBRID
security.provider.2=IBMJCECCA
security.provider.3=OpenJCEPlus
security.provider.4=IBMZSecurity

When we run our testcase again, we have a successful run...

Cipher text: 6d9f95b5f6d66b9b3edf6088f01602a2a8c72369c2863c40128a6297bacc22

So what happened? Why did the testcase work once IBMJCEHYBRID was added to the top of our provider list?

When we ran our testcase this time, the JCE framework called upon IBMJCEHYBRID to handle the encryption operation. Now that IBMJCEHYBRID has control, it first tries to recruit IBMJCECCA to perform the cipher because it is the next provider in the list. IBMJCECCA then tries to encrypt the plaintext using ICSF, but ultimately fails because ICSF is not available. IBMJCEHYBRID is notified that IBMJCECCA cannot perform the requested operation because the underlying hardware is disabled. IBMJCEHYBRID then begins it's failover ability by trying to recruit the next available provider to perform the operation instead - in this case it's OpenJCEPlus, another IBM security provider that utilizes hardware crypto, but it's underlying services include GSkit and ICC instead of ICSF.

IBMJCEHYBRID now asks OpenJCEPlus to perform the encryption instead. And since OpenJCEPlus is fully operational and does not rely on ICSF to perform functions, OpenJCEPlus encrypts the plaintext successfully and the program no longer breaks.

Conclusion

In this article, we've learned about the IBMJCEHYBRID security provider and how it can help your Java applications avoid potential issues due to volatile hardware cards and services. Hopefully this will encourage you to try IBMJCEHYBRID in your Java applications as well. Thanks for reading!

Further reading


How to obtain IBMJCEHYBRID

IBMJCEHYBRID is included in the IBM Semeru Runtime Certified Edition for z/OS download. Please follow the links below to download the IBM Semeru JDK onto your own machines.

 How to obtain IBM Semeru Runtime Certified Edition for z/OS?
IBM Semeru Runtime Certified Edition for z/OS is available for zero license charge through Shopz SMP/E, or you can download the non-SMP/E here. The subscription and service number is 5655-I48.

Supporting Links:
IBM Semeru Runtime Certified Edition for z/OS product page
For additional information on installation, troubleshooting and support please visit IBM Documentation.

0 comments
105 views

Permalink