SAF

The Java™ for z/OS® System Authorization Facility (SAF) interfaces provide an extra set of security APIs. The digital certificate support in SAF, and implementations in external security managers such as Resource Access Control Facility (RACF®), provide applications with an alternative to storing certificates and keys in data sets or files.

SAF security APIs provide access to z/OS UNIX APIs for implementing principal-based access control in a Java application. For example, in an application that implements a Java SecurityManager class. These APIs are implemented through Java classes that wrap z/OS UNIX Services. The z/OS UNIX Services are in turn handled by a security server for z/OS that implements SAF interfaces such as RACF. Applications that use these APIs do not have to be authorized by the authorized program facility (APF).

The JCECCARACFKS and JCERACFKS keystores in the SDK provide SAF digital certificate support, enabling the IBMJCECCA and IBMZSecurity providers to store and retrieve keys and certificates from SAF.

For more information about keystores, see Key Management in the Oracle documentation.

Digital certificate support is implemented as two keystore types: JCERACFKS and JCECCARACFKS. An InputStream class called RACFInputStream, an OutputStream class called RACFOutputStream, and a URLStreamHandler class are also implemented. The URLStreamHandler class enables a RACFInputStream or RACFOutputStream instance to be accessed by using a URL. URLStreamHandler objects are also available for both the IBMZSecurity zseckeytool program and the IBMJCECCA keytool program (hwkeytool) for z/OS. For more information about hwkeytool, see The hwkeytool key and certificate management utility.

The RACF keystore classes, JCERACFKS for the IBMZSecurity provider and JCECCARACFKS for the IBMJCECCA provider, are available only on the z/OS operating system where SAF is available.

A keystore class, JceRACFKeyStore, is implemented in both the IBMZSecurity and IBMJCECCA providers. This class is available for storing and retrieving certificates and keys from a RACF key ring. The RACFInputStream and RACFOutputStream classes are intended to be used only with the JceRACFKeyStore class. Use of the RACFInputStream or RACFOutputStream classes with other keystores might cause unexpected results.

All Java RACF services, including the JceRACFKeyStore, RACFInputStream, and RACFOutputStream classes, use the R_datalib (IRRSDL00) service to retrieve and store certificates from RACF. To use this service, certain authorizations must be granted to the user, depending on the setup that you want. Be sure to have the correct authorizations set for R_datalib before you use any Java RACF classes. For more information about how to set the necessary authorizations, see z/OS Security Server RACF Callable Services for your version of z/OS.

There are two ways to access keys and certificates that are stored in a SAF external security manager implementation by using the RACFInputStream and RACFOutputStream classes:
  • Use the RACFInputStream or RACFOutputStream classes directly by passing a newly created instance to the JceRACFKeyStore.
  • Use the URLStreamHandler class to call the RACFInputStream or RACFOutputStream classes indirectly then pass the instance into JceRACFKeyStore.
These methods are described in more detail in the next section.

The JCECCARACFKS and JCERACFKS keystores can store and retrieve certificates from a key ring that supports mixed case label and alias names. Use alias or label names that differ by at least 1 character from the names of the other alias or label names that are attached to the key ring. Do not use character alias or label names that differ only by case; such names can cause a search mismatch when storing or retrieving information from a JCECCARACFKS or JCERACFKS keystore.

Setting up a RACF key ring from RACF

When you set up a key ring, any certificate that is connected as a "PERSONAL" certificate is considered a KeyEntry object and therefore can be used as an end-user certificate (for example, in an SSL handshake) because the private key is available. Any certificate that is connected as a "CERTAUTH" certificate is considered a TrustedCertEntry object and can be used, for example, as a certificate authority (CA) certificate in the authentication process of SSL. Any key ring that has a certificate that is not self-signed and is connected as a "PERSONAL" certificate must also have the CA certificate of the "PERSONAL" certificate that is connected as "CERTAUTH". Self-signed certificates do not require a "CERTAUTH" certificate to be present. Certificates that are connected as "SITE" certificates are currently not supported. The following example shows the setup of a RACF key ring that can be used by a JSSE client and server for both trust and key information.

Certificate Label Name Cert Owner USAGE    DEFAULT
---------------------- ---------- -------- -------
PersonalEndUserCert    ID(USERID) PERSONAL YES
PersonalEndUserCACert  CERTAUTH   CERTAUTH NO
      

Using a RACFInputStream instance to load a RACF key ring into a Java RACF keystore

Creating a RACFInputStream instance requires these parameters:

  • userID: a string that contains the ID of the user that owns the key ring
  • ringid: a string that contains the name of the RACF key ring
  • password: a character array that contains the password for the keystore

The following example illustrates using a RACFInputSteam instance directly, passing it a user ID, a ring ID, and a null password.

import com.ibm.crypto.zsecurity.provider.RACFInputStream;

String ksfname;
char[] storePass = null;

RACFInputStream riStream = new RACFInputStream(System.getProperty("user.name"),
                                               ksfname,
                                               storePass);
KeyStore racfKeyStore = KeyStore.getInstance("JCERACFKS");
racfKeyStore.load(riStream, storePass);
riStream.close();
       

In the previous code example, the user.name system property is used to obtain the user ID to pass to RACF. In an actual application, this step will probably not be done.

Using a RACFOutputStream instance to store a Java RACF keystore into a RACF key ring

Creating a RACFOutputStream instance requires these parameters:

  • userID: a string that contains the ID of the user that owns the key ring
  • ringid: a string that contains the name of the RACF key ring
  • password: a character array that contains the password for the keystore

The following example illustrates using a RACFOutputStream instance directly, passing it a user ID, a ring ID, and a null password.

import com.ibm.crypto.zsecurity.provider.RACFOutputStream;

String ksfname;
char[] storePass = null;

RACFOutputStream roStream = new RACFOutputStream(System.getProperty("user.name"),
                                                 ksfname,
                                                 storePass);
KeyStore racfKeyStore = KeyStore.getInstance("JCERACFKS");
racfKeyStore.store(roStream, storePass);
roStream.close();
      

In the previous code example, the user.name system property is used to obtain the user ID to pass to RACF. In an actual application, this step will probably not be done.

Storing keys into RACF by using the RACFKeyStore class

The RACFKeyStore can be used to update an existing RACF key ring or create a new RACF key ring. If the RACF key ring that is specified by the user ID and ring name to the RACFOutputStream instance does not exist, the key ring is created. If the RACF key ring exists, it is updated. In either case, all certificates and keys in the keystore are added to the RACF key ring when the store method is called. When updating an existing RACF key ring, any existing RACF certificates and keys that are deleted are removed from the RACF key ring when the store method is called.

Entries that are deleted from the RACF keystore are removed from the RACF key ring, but the RACF certificate profile is not deleted from RACF. If a certificate is added that exists in RACF, but with a different label or alias, the certificate is added to the RACF key ring with the existing label, and an IOException instance is returned to indicate that the certificate exists with a different label or alias.

If an error is detected while updating a RACF key ring, all additional additions or deletions of entries are processed, but only the first error is reported as an exception.

The following scenario demonstrates this property:
  1. A RACFInputStream instance is created to specify an existing input RACF key ring.
  2. The RACFInputStream instance is loaded into a RACFKeyStore instance by using the RACFKeyStore.load() method.
  3. The input ring contains 1 key entry named Key01 and 1 trusted certificate entry named Cert01.
  4. Key01 is deleted by using the RACFKeyStore.delete() method.
  5. Two new key entries named Key02 and Key03 are added to the RACFKeyStore instance by using the RACFKeyStore.setKeyEntry() method.
  6. A RACFOutputStream instance is created to specify an output RACF key ring.
  7. The updates are written to the RACF key ring that is specified in the RACFOutputStream instance by using the RACFKeyStore.Store() method.
    1. First, the deletion entry is processed by successfully removing Key01 from the output RACF key ring.
    2. Next, all entries from the RACFKeyStore instance are added to the output RACF key ring.
    3. In this example, an error occurs while attempting to add Key02 to the output RACF key ring.
    4. Cert01 is added successfully to the output RACF key ring.
    5. An error occurs while attempting to add Key03 to the output RACF key ring.
  8. An exception is thrown with the details of the error that occurred while attempting to add Key02.

Accessing a RACFInputStream and RACFOutputStream instance by using the URLStreamHandler class

The URLStreamHandler class is required to enable access to data by using user-defined classes. You can use specific URLs and associated classes to access data that is stored in a SAF (RACF) key ring.

The following URL strings are supported.
safkeyring

When you use this URL, you must also specify the java.protocol.handler.pkgs system property. This property enables the URLStreamHandler class to create a RACFInputStream object. The safkeyring URL and associated classes access data that is stored in a SAF (RACF) key ring.

The value of the system property is the provider that you are using for cryptographic support. For example, if you are using the IBMJCECCA provider, set the system property as shown in this example:

java.protocol.handler.pkgs=com.ibm.crypto.hdwrCCA.provider
You can also set this property in a Java application, by using the java.lang.System.setProperty method:
System.setProperty("java.protocol.handler.pkgs", "com.ibm.crypto.hdwrCCA.provider");
If you use the safkeyring URL but you do not set the java.protocol.handler.pkgs system property, the following error occurs:
java.net.MalformedURLException: unknown protocol: safkeyring
Use the following syntax to specify the key ring and user ID:
"safkeyring://userid/keyring"
safkeyringjce | safkeyringjcehybrid | safkeyringjcecca

Support for these URLs was added in version 11 but is deprecated and might be removed in future releases.

Use the URL that corresponds with the type of RACF keystore that you want to access, as shown in the following table. You do not need to specify the java.protocol.handler.pkgs system property.
Table 1. SAF key ring URLs for different keystore types
Keystore type URL
JCECCARACFKS safkeyringjcecca
JCERACFKS safkeyringjce
JCEHYBRIDRACFKS safkeyringjcehybrid
Use the following syntax to specify the key ring and user ID for a keystore of type JCECCARACFKS:
"safkeyringjcecca://userid/keyring"

If you run an application that uses these URLs with a security manager enabled, a circular loading error occurs. For more information, see Known isues and limitations.

Supported key types for storing into a RACF keystore

The JCERACFKS RACF keystore supports the following Java key types:

  • RSAPrivateKey: software RSA format
  • RSAPrivateCrtKey: software RSA (in CRT) format
  • ECPrivateKey: software EC format

The JCECCARACFKS RACF keystore supports the following Java key types:

  • RSAPrivateKey: software RSA key format

    This key type is converted to RSAPrivateHWKey format

  • RSAPrivateCrtKey: software RSA (in CRT) format

    This key type is converted to RSAPrivateHWKey format

  • RSAPrivateHWKey: CLEAR RSA format with an external ICSF token

  • RSAPrivateHWKey: PKDS RSA format

  • ECPrivateKey: software EC key format

    This key type is converted to ECPrivateHWKey format

  • ECPrivateHWKey: CLEAR EC format with an external ICSF token

  • ECPrivateHWKey: PKDS EC format

No other key formats are supported.

Passwords and the RACF keystore

In file-based keystores, the password parameter is used for three primary reasons:

  • To protect the integrity of the keystore file
  • To protect keys in Java memory while they are used in a keystore
  • To protect keys when at rest in the file-based keystore

The password parameter is used differently by the RACF keystore. Because keys in the RACF keystore are stored in the RACF database rather than in a file, the password is used only to protect keys while the keystore is in Java memory. Digital certificates and keys in RACF key rings are protected by RACF profiles.

The following RACF keystore methods use the password parameter:
Table 2. RACF keystore methods and how they use the password parameter
Method Use of password parameter
RACFInputStream.RACFInputStream() To protect keys that are loaded from RACF in Java memory
JceRACFKeyStore.load() To validate that the input RACFInputStream instance is constructed with the same password
JceRACFKeyStore.setKeyEntry() To protect the input key
JceRACFKeyStore.getKeyEntry() To recover the protected key
JceRACFKeyStore.store() To validate that the input RACFOutputStream instance is constructed with the same password
RACFOutputStream.RACFOutputStream() To recover any protected keys from Java memory before storing them in a RACF key ring

In addition to keystore passwords, Java APIs enable an application to specify a password to protect an individual keystore entry. Within an instance of using the JceRACFKeyStore, RACFInputStream and RACFOutputStream to retrieve and set keys, the same password must be used. It is recommended that all passwords are allowed to use the default value.

The password parameter defaults to password on all methods by passing in null.

Updating a JCECCARACFKS KeyStore instance

A KeyStore instance is a Java object that contains a collection of keys and certificates that are referenced by unique labels or alias names. For most Java keystores, the persistent data is stored in a file. However, the persistent data for a JCECCARACFKS keystore is stored in the RACF database and connected to a RACF key ring. Due to the nature of the RACF database and key rings, the behavior of a JCECCARACFKS keystore during update operations differs from the behavior of file-based keystores.

In the following discussion, application can refer to a user KeyStore application or the hwkeytool utility.

Keystore load and update operations

To access the contents of a keystore, an application uses the load() method to retrieve the persistent data from the keystore and create a KeyStore object. This object can be queried and updated by the application. KeyStore update methods include deleteEntry(), setEntry(), setCertificateEntry(), and setKeyEntry(). The hwkeytool update commands that are supported for RACF keystores include -delete, -genkeypair, -importcert, and -importkeystore.

If the application intends to modify the persistent data for the keystore, it uses the store() method. The behavior of the store() method depends on the underlying storage of the persistent data.

File-based keystores and the KeyStore store() method

The update model for file-based keystores is a replace model. When the application uses the store() method for a file-based keystore, the contents of the KeyStore object in the application memory replace the current persistent data for the keystore. In other words, any KeyStore update that is successful is reflected in the new version of the persistent data for the keystore.

One consequence of the replace model occurs if two applications are updating the same keystore at the same time. To illustrate, suppose application app1 and application app2 modify the same keystore in the following sequence:

  1. app1 loads the keystore into a KeyStore object and makes some updates
  2. app2 loads the keystore into a KeyStore object and makes some updates
  3. app1 stores the contents of the KeyStore object into the persistent keystore data
  4. app2 stores the contents of the KeyStore object into the persistent keystore data

In this scenario, because the app1 changes were not stored in persistent data before app2 loaded the keystore, and because app2 replaced the persistent data after app1, updates that were made by app1 are overwritten by app2.

RACF keystores and the KeyStore store() method

The update model for a JCECCARACFKS keystore is an update model. It was implemented in this way to avoid the effect described previously. If a change is made to an existing KeyStore entry, the existing version of the entry is disconnected from the key ring, the data for the new entry is added to the RACF database, then the new entry is connected to the key ring. Even if the update is a delete operation, whether deleteEntry() or hwkeytool -delete, the data is not removed from the RACF database, it is only disconnected from the key ring that represented by the KeyStore object. To delete data from the RACF database, you must use the RACF utility RACDCERT.

The following RACF database and key ring updates are not permitted:

  • An entry with an expired certificate cannot be updated.
  • An entry cannot be updated with an expired certificate.
  • A certificate entry cannot be replaced with a key entry.
  • A key entry cannot be replaced with a certificate entry.
  • An entry cannot be updated unless the public key in the new version matches the public key in the existing version.
  • Although a single certificate can be connected to many key rings, there can be only one copy of it in the RACF database and it is stored with only one label.

When the IBMJCECCA security provider detects an update that is not allowed by RACF, an exception is thrown when the KeyStore entry update is attempted. In some cases, the IBMJCECCA security provider cannot predict that a RACF database update will be unsuccessful. One consequence of this is that a KeyStore update might be successful but an error or warning is reported during the store() operation.

Some possible effects of this behavior are as follows:

  • The previous version of the entry is disconnected from the key ring and the new version is not connected to the key ring.
  • A certificate might be connected to the key ring by using a label other than the one that is specified in the KeyStore update.

If there are unintended and undesired changes to a keystore, it might be necessary to reconnect or to update key ring entries by using the RACF utility RACDCERT.

Additional Information:

For the SAF API reference documentation, see Sytem Authorization Facility (SAF) in the security API reference.

For more information about inserting or updating information in the RACF External Security Manager, see the RACDCERT documentation for your version of z/OS. The following documentation is also available for RACF: