A Practical Look at z/OS-specific Java Security Exploitation
Setup
- Requires ICSF installation and initiation
- Remember to activate hardware
- The IBMJCE4758 provider needs to be added to the provider list either statically in the file ${java-home}/lib/security/java.security
security.provider.1=com.ibm.crypto.hdwrCCA.provider.IBMJCE4758
security.provider.2=com.ibm.crypto.provider.IBMJCE
...
or adding the provider at run time
Security.insertProviderAt(
new com.ibm.crypto.hdwrCCA.provider.IBMJCE4758(), 1);
Policy files
- Full Function versus Limited Key Size Cryptography
- Default: US_export_policy.jar and local_policy.jar pre-installed in directory ${java-home}/lib/security: limited function cryptography with no export restrictions
- Download unrestricted policy files
- Replace files US_export_policy.jar and local_policy.jar in the ${java-home}/lib/security: full function cryptography
- also available in ${java-home}/demo/jce/policy-files
/* The Java framework APIs are used to generate a DES key. */
KeyGenerator desKeyGen = KeyGenerator.getInstance("DES",
"IBMJCE4758");
SecretKey key = desKeyGen.generateKey();
/* The piece of data that we are going to encrypt/decrypt
sign/verify. */
byte[] plaintext = "This is a test message to play
with".getBytes();
/* Using the DES key previously generated we can encrypt then
decrypt a piece of data. */
Cipher cp = Cipher.getInstance("DES", "IBMJCE4758");
cp.init(Cipher.ENCRYPT_MODE, key);
byte[] cipherText = cp.doFinal(plainText);
cp.init(Cipher.DECRYPT_MODE, key, cp.getParameters());
byte[] newPlainText = cp.doFinal(cipherText);
/*
The Java framework APIs of java are used to generate a
JCE4758 hardware RSA key pair. We can then obtain the public
key and private key of the key pair.
*/
KeyPairGenerator rsaKeyPairGen =
KeyPairGenerator.getInstance("RSA","IBMJCE4758");
RSAKeyParameterSpec keySpec = new RSAKeyParameterSpec(1024,
KeyHWAttributeValues.CLEAR,
KeyHWAttributeValues.KEYMANAGEMENT);
rsaKeyPairGen.initialize(keySpec);
KeyPair rsaKeyPair = rsaKeyPairGen.generateKeyPair();
PublicKey rsaPub = rsaKeyPair.getPublic();
PrivateKey rsaPriv = rsaKeyPair.getPrivate();
/*
Using the RSA key pair that we previously generated we can
sign a piece of data with the private key then verify that
same piece of data using the public key.
*/
Signature sig = Signature.getInstance
("SHA1withRSA", "IBMJCE4758");
sig.initSign(rsaPriv);
sig.update(plainText);
byte[] signature = sig.sign();
sig.initVerify(rsaPub);
sig.update(plainText);
boolean result = sig.verify(signature);
/* Load the keystore from a given file. */
KeyStore keyStore = KeyStore.getInstance("JCE4758KS");
char[] storepass = "storepass".toCharArray();
char[] keypass = "keypass".toCharArray();
FileInputStream storeStream =
new FileInputStream("jce4758store");
keyStore.load(storeStream, storepass);
/*
Get the private and public keys of "mykey". A key
entry in a keystore contains the private key and the
certificate or certificate chain associated with it.
We can get our certificate by calling
KeyStore.getCertificate() for an alias that
identifies a key entry.
*/
PrivateKey privKey =
(PrivateKey)keyStore.getKey("mykey", keypass);
Certificate cert = keyStore.getCertificate("mykey");
PublicKey pubKey = cert.getPublicKey();
hwkeytool -genkey \
-keyalg RSA \
-keysize 1024 \
-sigalg MD5withRSA \
-validity 365 \
-alias mykey \
-dname "CN=IBM User, O=IBM, C=US" \
-storetype jce4758ks \
-storepass storepw \
-keypass keypw \
-keystore ~/.HWkeystore \
-keylabel keylbl \
-hardwareusage KEYMANAGEMENT \
-hardwaretype CLEAR \
-provider com.ibm.crypto.hdwrCCA.provider.
IBMJCE4758 \
-v
Setup
- In order to use SAF certificates for trust or key information, IBMCertPath provider needs to be in the java.security provider list or added at runtime. For example:
Security.addProvider(new com.ibm.security.cert.IBMCertPath());
/* Get certificates and keys from RACF */
RACFInputStream ksStream =
new RACFInputStream("userid", "hwring", null);
KeyStore keyStore =
KeyStore.getInstance("JCE4758RACFKS");
keyStore.load(ksStream, null);
/* Get the private and public key associated with the
specified alias */
Key privKey = keyStore.getKey("hwkey", null);
PublicKey pubKey =
keyStore.getCertificate("hwkey").getPublicKey();
/* Get certificates and keys from RACF */
RACFInputStream ksStream =
new RACFInputStream("userid", "aring", null);
KeyStore keyStore =
KeyStore.getInstance("JCERACFKS");
keyStore.load(ksStream, null);
/* Get the private and public key associated with the
specified alias */
Key privKey = keyStore.getKey("akey", null);
PublicKey pubKey =
keyStore.getCertificate("akey").getPublicKey();
keytool -list \
-storetype JCERACFKS \
-keystore safkeyring:///aring \
-J-Djava.protocol.handler.pkgs=com.ibm.crypto.
provider
hwkeytool -list \
-storetype JCE4758RACFKS \
-keystore safkeyring:///hwring \
-J-Djava.protocol.handler.pkgs=
com.ibm.crypto.hdwrCCA.provider
IBMJSSE Setup Issues
Initializing SSL context
/*
Create the RACFInputStream that gives us access to a
particular SAF key ring. In this case use userid
"" to access the key ring
"ServerKeyring" and use the password "passphrase" to
protect the in memory representation of the RACF
key ring.
*/
KeyStore ks = KeyStore.getInstance("JCERACFKS");
com.ibm.crypto.provider.RACFInputStream inputStream =
new com.ibm.crypto.provider.RACFInputStream
("",
"ServerKeyring",
"passphrase".toCharArray());
ks.load(inputStream, "passphrase".toCharArray());
/* Initialize the key manager */
KeyManagerFactory kmf =
KeyManagerFactory.getInstance("IbmX509");
kmf.init(ks, "passphrase".toCharArray());
/* Initialize the trust manager */
TrustManagerFactory tmf =
TrustManagerFactory.getInstance("IbmX509");
tmf.init(ks);
/* Initialize the SSL context */
sslContext = (SSLContext)SSLContext.getInstance("SSL");
sslContext.init(kmf.getKeyManagers(),
tmf.getTrustManagers(), null);
Getting an SSL session (server)
/* Get and print the list of supported enabled
cipher suites */
String enabled[] =
sslContext.getSocketFactory().getSupportedCipherSuites();
for (i=0; i < enabled.length; i++)
System.out.println(enabled[i]);
/* Create an SSL session over port 8070 */
SSLServerSocketFactory factory =
sslContext.getServerSocketFactory();
SSLServerSocket ssl_server_sock =
(SSLServerSocket)factory.createServerSocket(8070);
SSLSocket ssl_sock;
ssl_sock = (SSLSocket)(ssl_server_sock.accept());
ssl_sock.setEnabledCipherSuites(enabled);
ssl_sock.startHandshake();
SSLSession session = ssl_sock.getSession();
System.out.println("\nServerJsse: SSL
connection established");
System.out.println(" cipher suite: "
+ session.getCipherSuite());
Initializing SSL context
/*
Initialize the KeyManagerFactory using the IBMJCE4758
provider as the provider for crypto operations
*/
KeyStore ks = KeyStore.getInstance("JCE4758KS");
ks.load(new FileInputStream("testkeys.4758"),
"passphrase".toCharArray());
KeyManagerFactory kmf =
KeyManagerFactory.getInstance("IbmX509");
KeyManagerFactoryParametersSpec parms =
new KeyManagerFactoryParametersSpec (ks,
"passphrase".toCharArray(),
"IBMJCE4758");
kmf.init(parms);
/* Initialize the trust manager */
TrustManagerFactory tmf =
TrustManagerFactory.getInstance("IbmX509");
tmf.init(ks);
/* Initialize the SSL context */
SSLContext sslContext = SSLContext.getInstance("SSL");
sslContext.init(kmf.getKeyManagers(),
tmf.getTrustManagers(), null);
Getting an SSL session (server)
/* Create an SSL session over port 8070 */
SSLServerSocketFactory factory =
sslContext.getServerSocketFactory();
SSLServerSocket ssl_server_sock =
(SSLServerSocket)factory.createServerSocket(8070);
SSLSocket ssl_sock;
ssl_sock = (SSLSocket)(ssl_server_sock.accept());
ssl_sock.setEnabledCipherSuites(enabled);
ssl_sock.startHandshake();
SSLSession session = ssl_sock.getSession();
System.out.println("\nServerJsse4758Provider:
SSL connection established");
System.out.println(" cipher suite: "
+ session.getCipherSuite());
Initializing SSL context
/*
Add the URL handler to the handler property. This
informs IBMJSSE what URL handler to use to handle
the safkeyring support. In this case IBMJCE.
*/
System.setProperty("java.protocol.handler.pkgs",
"com.ibm.crypto.provider");
/*
Set the system properties which say what keystore
to use for IBMJSSE's key information. The key store
contains the end user personal certificates that are
used in the authentication process.
*/
System.setProperty("javax.net.ssl.keyStore",
"safkeyring:///ServerKeyring");
System.setProperty("javax.net.ssl.keyStoreType",
"JCERACFKS");
System.setProperty("javax.net.ssl.keyStorePassword",
"password");
/* Initialize the key manager */
KeyManagerFactory kmf = KeyManagerFactory.getInstance
("IbmX509");
KeyStore ks = null;
kmf.init(ks, null);
/*
Set the system properties which say what truststore
to use for JSSE's trust information. The trust store
contains the CA certificates that are used in the
authentication process.
*/
System.setProperty("javax.net.ssl.trustStore",
"safkeyring://userid/ServerKeyring");
System.setProperty("javax.net.ssl.trustStoreType",
"JCERACFKS");
System.setProperty("javax.net.ssl.trustStorePassword",
"password");
/* Initialize the trust manager */
TrustManagerFactory tmf = TrustManagerFactory.getInstance
("IbmX509");
tmf.init(ks);
/* Initialize the SSL context */
SSLContext sslContext = SSLContext.getInstance("SSL");
sslContext.init(kmf.getKeyManagers(),
tmf.getTrustManagers(), null);
Getting an SSL session (server)
/* Create an SSL session over port 8050 */
SSLServerSocketFactory factory =
sslContext.getServerSocketFactory();
SSLServerSocket ssl_server_sock =
(SSLServerSocket)factory.createServerSocket(8050);
SSLSocket ssl_sock;
ssl_sock = (SSLSocket)(ssl_server_sock.accept());
ssl_sock.setEnabledCipherSuites(enabled);
ssl_sock.startHandshake();
SSLSession session = ssl_sock.getSession();
System.out.println("\nServerJsse: SSL connection
established");
System.out.println(" cipher suite: "
+ session.getCipherSuite());
/* REXX */
ADDRESS TSO
/* Delete all the certificates. */
"RACDCERT DELETE (LABEL('hwkey'))"
"RACDCERT DELETE (LABEL('cacert'))"
/* Delete the key ring. */
"RACDCERT DELRING(hwring)"
/* Creating a key ring. */
"RACDCERT ADDRING(hwring)"
/* Generating the certificates */
"RACDCERT GENCERT SUBJECTSDN(CN('Trusted Certificate')
C('US')) " || ,
"WITHLABEL('cacert') TRUST ICSF"
"RACDCERT GENCERT SUBJECTSDN(CN('PK hwkey') O('IBM')) " || ,
"WITHLABEL('hwkey') SIGNWITH(LABEL('cacert')) ICSF"
/* Connecting Certificates to their key rings */
"RACDCERT CONNECT (LABEL('cacert') RING(hwring)
USAGE(CERTAUTH))"
"RACDCERT CONNECT (LABEL('hwkey') RING(hwring) DEFAULT
USAGE(PERSONAL))"
/* Facility class refresh */
"SETROPTS RACLIST(FACILITY) REFRESH"
/* List the key ring */
"RACDCERT LISTRING(hwring)"
These are working code samples that may be used without royalty or license. They are provided as-is.
Samples
|