I had been trying to follow some instructions on how to use a z/OS keyring in a Java application, but I was having lots of error messages and little success. Searching the internet did not help because most of the documentation on the internet does not tell you what version of Java they were using; but fortunately I managed to stumble on the magic combination of options which worked.
I ended up with one of my configuration files with information for Java 8 and Java 11, which I had to clean up.
There are several pieces of the puzzle, all which have to be right.
- Recent Java versions were better than old ones. Java V8 SR8 FP6 from 2023 was better than Java V8 SR6 FP19 from 2020
- The java.security file; this contains the master set of security definitions for the system. Your application can override options within this file, or use a totally different file
- Which jar file to use.
- Which classes to use – specifying the high level qualifier
- How you specify your keyring for example safkeyring://START1/MQRING, or safkeyringjce://START1/MQRING
- Which Java start up overrides your Java program uses.
What worked for me
On Java 8 the following are typical default values
- -Djava.protocol.handler.pkgs=com.ibm.crypto.provider
- -Djavax.net.ssl.keyStoreType=JCERACFKS
- -Djavax.net.ssl.keyStore=safkeyring://START1/MQRING
Because I was using Apache Tomcat web server, some of the definitions were taken from the server.xml file, and override the -Djavax.net.ssl.keyStoreType and -Djavax.net.ssl.keyStore parameters.
RSEAPI_KEYSTORE_FILE="safkeyring://START1/MQRING " RSEAPI_KEYSTORE_TYPE="JCERACFKS"
The Java security file.
The default file is /usr/lpp/java/J8.0/lib/security/java.security or /usr/lpp/java/J8.0_64/lib/security/java.security depending on which JVM you are using (31 bit or 64 bit).
You can override this using
- -Djava.security.properties==/etc/zexpl/java.security to specify which file to use instead of the default file.
- -Djava.security.properties=/etc/zexpl/java.security for entries in the specified file to override the entries in the default file.
The content of interest is like
security.provider.1=com.ibm.jsse2.IBMJSSEProvider2 security.provider.2=com.ibm.crypto.provider.IBMJCE security.provider.3=com.ibm.crypto.plus.provider.IBMJCEPlus security.provider.4=com.ibm.security.jgss.IBMJGSSProvider security.provider.5=com.ibm.security.cert.IBMCertPath security.provider.6=com.ibm.security.sasl.IBMSASL
I’ll explain what this means below.
Which classes – the high level qualifier
This is defined like -Djava.protocol.handler.pkgs=com.ibm.crypto.provider
This usage is explained below.
How Java loads things
My explanation below may be wrong – but it should give the concepts.
- By some magic Java know which classes are in which jars. (Java may look in every jar at startup).
- My keying is defined as safkeyring://START1/MQRING.
- I have -Djava.protocol.handler.pkgs=com.ibm.crypto.provider
- Java combines this information and looks through the classes for com.ibm.crypto.provider.safkeyring.Handler class.
- It finds the class in /usr/lpp/java/J8.0/lib/ext/ibmjceprovider.jar
If there are more than one potential class, it take the in the Jar file in the security.provider.n list.
When I used –Djava.protocol.handler.pkgs=com.ibm.crypto.hdwrCCA.provider, it searched for class com.ibm.crypto.hdwrCCA.provider.safkeyring.Handler which was in /usr/lpp/java/J8.0_64/lib/ext/ibmjcecca.jar .
When I used -Djava.protocol.handler.pkgs=com.ibm.crypto.hdwrCCA.provider, initially I got an ICSF security violation ( which was good news as it showed I was using ICSF). Once I fixed the security problem I got a Java exception
org.apache.catalina.LifecycleException: Protocol handler initialization failed Caused by: java.lang.IllegalArgumentException: Invalid keystore format Caused by: java.io.IOException: Invalid keystore format
There is documentation but I could not get round this problem
If I stopped ICSF (p CSF) I got Java exceptions
java.security.NoSuchAlgorithmException: no such algorithm: EC for provider IBMJCECCA
What did not work for me
IBMJCEPlus
There was a reference which said in order to use TLS V1.3 you need to use IBMJCEPlus.
I overrode the java.security file by using
security.provider.1=com.ibm.crypto.plus.provider.IBMJCEPlus
but this gave a Java exception
java.security.ProviderException: Could not load dependent library
which looks like it could not load a load module (.so) from the file system.
Upgrading the Java fixpack worked for me
I upgraded the level of Java V8 from 2020 to a 2023 version, going from fix pack16 to fix pack 25, and lots of problems went away.
Java 11
Java 11 has different provider of the keyring support.
security.provider.1=OpenJCEPlus
security.provider.2=IBMZSecurity
security.provider.3=SUN
security.provider.4=SunRsaSign
security.provider.5=SunEC
security.provider.6=SunJSSE
security.provider.7=SunJCE
security.provider.8=SunJGSS
security.provider.9=SunSASL
security.provider.10=XMLDSig
security.provider.11=SunPCSC
I did not try to use these, as the application I was using did not support Java 11.
There is some documentation on Java 11 and security.