Introduction
During JVM initialization, the Java Security Framework loads each security provider listed in the java.security provider list. When a provider initializes itself, it registers with the Java Security Framework for each serviceType.algorithm that it can perform. If an application requests cryptographic services without specifying a security provider, the Java Security Framework selects the first provider in the security provider list that registered the requested service.
An application that uses services provided by security providers can specify the provider it wants to use. However, applications don't usually do this because it makes them less portable and less flexible. In addition, by using the installation-configured provider list, an application can take advantage of crytographic features when running on a platform that includes them and also can run successfully on a platform that does not include cryptographic features.
Because a platform with cryptographic features (such as cryptographic hardware and cryptographic processors) can be volatile, a security provider might register for a serviceType.algorithm that it is unable to perform when requested. In this case, the security provider will throw an exception that is passed up to the application. If the application retries the operation, the Security Framework will pass the request to the same provider because it is still first in the list. Unless there is a change in the status of cryptographic features on the platform, the result will be the same. Thus the application will be unsuccessful, even if another provider registered for the serviceType.algorithm could successfully process the request.
The IBM JCE Hybrid Provider is designed to provide failover from one JCE security provider to another in a manner that is transparent to applications.
IBMJCEHYBRID Failover with JCE Providers
IBMJCEHYBRID does not perform any cryptographic operations, but routes requests to JCE providers that have registered with the Java Security Framework. When IBMJCEHYBRID is the first JCE provider in the active JVM provider list (initialized using the java.security provider list), IBMJCEHYBRID routes requests to and provides failover for JCE providers according to the security provider registrations done at JVM initialization. This enables an application to take advantage of cryptographic features when they are available on the platform and to use a provider that does not depend on these features when they are not available.
If IBMJCEHYBRID is not the first JCE provider in the active JVM provider list then a cryptographic request might be routed to a different JCE provider instead of IBMJCEHYBRID. If this happens, IBMJCEHYBRID does not get control and cannot provide routing or failover for the request. The IBMJCEHYBRID can be the first JCE provider in the java.security provider list but not be the first JCE provider in the active JVM provider list. This will be the case if an application uses the Security.insertProviderAt() API and inserts a provider ahead of IBMJCEHYBRID.
The list of serviceType.algorithm pairs for which IBMJCEHYBRID provides failover is the list of serviceType.algorithm pairs supported by either the IBMJCECCA provider or the IBMJCE provider, with the exception of algorithms in the KeyStore service. Using this list, IBMJCEHYBRID provides failover from, and to, each provider in the java.security provider list, whether it is an IBM security provider, a security provider written by the customer, or a third party security provider.
KeyStore support is, in general, very specific to the implementing provider. In other words, if a provider can not satisfy a KeyStore request for a KeyStore that it implements then it is very unlikely that another provider can satisfy a request for that KeyStore. For this reason, IBMJCEHYBRID does not attempt failover for any KeyStore.algorithm. When the Java Security Framework receives a request for a serviceType.algorithm that IBMJCEHYBRID has not registered, then the Framework routes the request to the first security provider that has registered for it.
IBMJCEHYBRID routes requests to and provides failover for only those providers that are in the java.security provider list when the JVM initializes the Security Framework. If an application uses the Security.insertProviderAt() API to insert a JCE provider after IBMJCEHYBRID, IBMJCEHYBRID will continue to be the preferred provider and will continue to provide failover support. However, IBMJCEHYBRID will not route requests to or provide failover for the provider that was inserted. Consequently, unless an application specifies the inserted JCE provider on the getInstance() API, it will receive control only for serviceType.algorithm pairs that IBMJCEHYBRID did not register.
If a JCE provider in the active JVM provider list has dependencies on cryptographic features that are offline then repeated calls to that provider will impose a performance penalty. To reduce the effect of this performance penalty, if a provider fails to process a request for a serviceType.algorithm it registered, that provider is marked 'inactive' for that serviceType.algorithm. Because the cryptographic features might become available, inactive providers are periodically restored to 'active' status based on a number of factors, including how often there is a getInstance() for the serviceType.algorithm and the state of the active providers list when request failovers are processed. If a request cannot be processed by any active provider, all inactive providers are restored to active status and IBMJCEHYBRID attempts to failover to each of them in turn.
Examples of IBMJCEHYBRID Failover with JCE Providers
The following examples illustrate the failover service provided by IBMJCEHYBRID:
Example 1
JCE providers in the JVM security provider list are as follows:
- IBMJCEHYBRID
- IBMJCECCA
- IBMJCE
Processing flow:
- An application requests a serviceType.algorithm supported by both IBMJCECCA and IBMJCE. The application does not specify a provider on getInstance().
- IBMJCEHYBRID gets control and routes the request to IBMJCECCA.
- If IBMJCECCA is unable to process the request it throws an exception, IBMJCEHYBRID catches the exception and attempts to failover to IBMJCE.
Example 2
JCE providers in the JVM security provider list are as follows:
- IBMJCEHYBRID
- IBMJCECCA
- IBMJCE
Processing flow:
- An application requests a serviceType.algorithm supported by IBMJCE but not supported by IBMJCECCA. The application does not specify a provider on getInstance().
- IBMJCEHYBRID gets control and routes the request to IBMJCE.
- If IBMJCE is unable to process the request it throws an exception, IBMJCEHYBRID catches the exception, wraps it in an IBMJCEHybridException and throws it to the application.
Example 3
JCE providers in the JVM security provider list are as follows:
- IBMJCEHYBRID
- IBMJCECCA
- IBMJCE
Processing flow:
- An application requests a serviceType.algorithm supported by both IBMJCECCA and IBMJCE. The application does not specify a provider on getInstance().
- IBMJCEHYBRID gets control and routes the request to IBMJCECCA.
- If IBMJCECCA is unable to process the request it throws an exception, IBMJCEHYBRID catches the exception and attempts to failover to IBMJCE.
- If IBMJCE is unable to process the request it throws an exception, IBMJCEHYBRID catches the exception, wraps both the exception thrown by IBMJCECCA and the exception thrown by IBMJCE in an IBMJCEHybridException and throws it to the application.
Example 4
JCE providers in the JVM security provider list are as follows:
- IBMJCE
- IBMJCECCA
- IBMJCEHYBRID
Processing flow:
- An application requests a serviceType.algorithm supported by both IBMJCECCA and IBMJCE. The application does not specify a provider on getInstance().
- IBMJCE gets control.
- IBMJCE is unable to process the request and throws an exception.
- The exception is passed back to the application. (No failover is done because IBMJCEHYBRID does not get control.)
Example 5
JCE providers in the JVM security provider list are as follows:
- IBMJCECCA
- IBMJCE
Processing flow:
- An application invokes Security.insertProviderAt(new com.ibm.crypto.ibmjcehybrid.provider.IBMJCEHYBRID, 1)
- The application requests a serviceType.algorithm supported by both IBMJCECCA and IBMJCE. The application does not specify a provider on getInstance().
- IBMJCEHYBRID gets control and routes the request to IBMJCECCA.
- If IBMJCECCA is unable to process the request it throws an exception, IBMJCEHYBRID catches the exception and attempts to failover to IBMJCE.
Example 6
JCE providers in the JVM security provider list are as follows:
- IBMJCEHYBRID
- IBMJCECCA
- IBMJCE
Processing flow:
- An application invokes Security.insertProviderAt(new mypkg.MyProvider, 1)
- The application requests a serviceType.algorithm supported by MyProvider, by IBMJCECCA, and by IBMJCE. The application does not specify a provider on getInstance().
- MyProvider gets control.
- MyProvider is unable to process the request and throws an exception.
- The exception is passed back to the application. (No failover is done because IBMJCEHYBRID does not get control.)
Example 7
JCE providers in the JVM security provider list are as follows:
- IBMJCEHYBRID
- IBMJCECCA
- IBMJCE
Processing flow:
- An application invokes Security.insertProviderAt(new mypkg.MyProvider, 3)
- The application requests a serviceType.algorithm supported by MyProvider, by IBMJCECCA, and by IBMJCE. The application does not specify a provider on getInstance().
- IBMJCEHYBRID gets control and routes the request to IBMJCECCA.
- If IBMJCECCA is unable to process the request it throws an exception, IBMJCEHYBRID catches the exception and attempts to failover to IBMJCE.
- If IBMJCE is unable to process the request it throws an exception, IBMJCEHYBRID catches the exception, wraps both the exception thrown by IBMJCECCA and the exception thrown by IBMJCE in an IBMJCEHybridException and throws it to the application. (There is no failover to MyProvider because it was not in the provider list at JVM initialization.)
IBMJCEHYBRID Failover and Security Object State
As described in the previous section, the ability of IBMJCEHYBRID to provide failover depends on the JCE security providers that have registered with the Java Security Framework. The ability of IBMJCEHYBRID to provide failover also depends on the state of the security object, specifically on the type of data that has been passed to the security object.
In general,
- Passing specification information, such as chaining mode or padding scheme, will not prevent failover to another provider.
- Passing data, such as an encryption key or bytes of data to be encrypted, will prevent failover after the first time. That is, if there is a failure during the first call that passes data, IBMJCEHYBRID will attempt failover. If the first such call is successful then failover is disabled for the object until after a reset operation, even if the subsequent failure is in a method that does not itself prevent failover.
- A reset, explicit or implicit, will reenable failover. An explicit reset occurs when an implementation SPI has a reset() method and it is called by an application. An implicit reset occurs when an application calls a method that includes a reset operation, as described in the Java Specification. Examples of methods that include reset are the Cipher SPI doFinal() method and the Signature SPI sign() and verify() methods.
If Failover is unsuccessful: IBMJCEHybridException
As described in the preceding sections, IBMJCEHYBRID provides failover when JCE providers are unable to complete cryptographic operations. Depending on the circumstances of the request and the platform environment, failover may not be successful. For example, failover could be unsuccessful due to the state of the operation when failover was attempted or due to an incorrectly formed request.
If failover is successful, it is transparent to the application. In this case, no error is reported and no exception is thrown.
If failover is not successful, IBMJCEHYBRID throws an IBMJCEHybridException
containing the exception (and stack trace) thrown by each JCE provider that attempted the
operation. These embedded exceptions are included in the output from printStackTrace()
.
The embedded exceptions can also be retrieved programmatically.
The following is an example of the output from ex.printStackTrace()
where ex
is an IBMJCEHybridException
. In this example, IBMJCECCA
was first in the provider list for the RSA Cipher and IBMJCE was second (and last). IBMJCECCA
failed the request with a ShortBufferException. IBMJCE failed the request because the key
was an IBMJCECCA hardware key, a format not recognized by IBMJCE. (Note that both IBMJCECCA
and IBMJCE recognize the format of an IBMJCE key. If the key had been in this format, failover
would have resulted in two ShortBufferExceptions.)
The following illustrates how to retrieve the embedded exceptions from the
IBMJCEHybridException
programatically.
Configuration Details
To enable the IBMJCEHYBRID provider, you can add it as the first JCE provider in the provider list in $JAVA_HOME/lib/security/java.security.
The following example shows the configuration needed for IBMJCEHYBRID to provide failover from the IBMJCECCA provider to the IBMJCE provider for serviceType.algorithm pairs for which both are registered.
Note that IBMJCEHYBRID can also be enabled by an application invoking
However, this might impact the portability of the application.
JCEHYBRIDRACFKS KeyStore Implementation
The IBMJCEHYBRID provider contains a KeyStore implementation called
JCEHYBRIDRACFKS. This keystore allows a user to load a single SAF keyring as
both a JCECCARACFKS and JCERACFKS keystore representation. When loaded the new
JCEHYBRIDRACFKS will contain a combination of the key and certificate material from
both the JCECCARACFKS and JCERACFKS keystore representations of the same SAF
keyring. This combination will be stored in a key container which contains all of the
available key material from both keystores. Please see the IBMJCECCA documentation
titled z/OS Unique Considerations
for more information regarding the
JCECCARACFKS and JCERACFKS keystores.
When a SAF keyring is loaded as a JCEHYBRIDRACFKS KeyStore the keyring will be loaded as both a JCECCARACFKS and a JCERACFKS keystore. The key material from both of these keystores will be combined together and represented by the JCEHYBRIDRACFKS keystore. The various pieces that are to be available by the user of the JCEHYBRIDRACFKS KeyStore can be described by the following table. The left most column shows the keyring being loaded, the middle column shows the results of what will be available when ICSF is turned on and no errors occur during loading of the keystore, and the right most column shows the results of what will be available when ICSF is turned off or errors occur during loading of the keystore.
Note that any certificates/keys in the table ending with the name CCA have their key material located within ICSF.
Keyring Being Loaded | ICSF Turned On ( During Load ) Keystore Contents Available | ICSF Turned Off ( During Load ) Keystore Contents Available |
---|---|---|
Ring: >Keyring< Certificate Cert Owner USAGE DEFAULT ------------------------------------------------- JayCa ID(G910501) CERTAUTH NO JayEndUser ID(G910501) PERSONAL YES |
JayCa entry contains: Certificate JayEndUser entry contains: Certificate Certificate chain IBMJCECCA private key IBMJCE private key |
JayCa entry contains: Certificate JayEndUser entry contains: Certificate Certificate chain IBMJCE private key |
Ring: >KeyringCCA< Certificate Cert Owner USAGE DEFAULT ------------------------------------------------- JayCaCCA ID(G910501) CERTAUTH NO JayEndUserCCA ID(G910501) PERSONAL YES |
JayCaCCA entry contains: Certificate JayEndUserCCA entry contains: Certificate Certificate chain IBMJCECCA private key |
JayCaCCA entry contains: Certificate JayEndUserCCA Alias will be unavailable since ICSF is down and key resides in ICSF. JayCa entry contains: Certificate JayEndUser entry contains: Certificate Certificate chain IBMJCE private key |
Ring: >KeyringMix< Certificate Cert Owner USAGE DEFAULT ------------------------------------------------- JayCa ID(G910501) CERTAUTH NO JayEndUser ID(G910501) PERSONAL NO JayCaCCA ID(G910501) CERTAUTH NO JayEndUserCCA ID(G910501) PERSONAL YES |
JayCa entry contains: Certificate JayCaCCA entry contains: Certificate JayEndUserCCA entry contains: Certificate Certificate chain IBMJCECCA private key JayEndUser entry contains: Certificate Certificate chain IBMJCECCA private key IBMJCE private key |
JayCa entry contains: Certificate JayCaCCA entry contains: Certificate JayEndUserCCA Alias will be unavailable since ICSF is down and key resides in ICSF. JayEndUser entry contains: Certificate Certificate chain IBMJCE private key |
KeyStore operations that create new entries or update existing entries will accept either a key derived from the IBMJCE provider or a key derived from the IBMJCECCA provider and will store them in the instance of the JCEHYBRIDRACFKS keystore along with inserting them into the underlying keystore of choice. Keys derived from the IBMJCECCA provider will be inserted into the underlying JCECCARACFKS keystore, keys derived from the IBMJCE provider will be inserted into the underlying JCERACFKS keystore.
KeyStore operations that return key entries will return a new private key called HybridRACFPrivateKey. KeyStore operations that return generic certificate objects will return certificates. This means that the exact nature of the key or certificate returned by KeyStore APIs (getKey(), getCertificate(), and getCertificateChain()) does not always need to be known to the application. The HybridRACFPrivateKey or certificate can be retrieved and passed to an instance of the crypto API as a generic Key or Certificate object. That being said only cipher and signature instances derived from the IBMJCEHYBRID provider will be able to make use of the new HybridRACFPrivateKey object for RSA signature and cipher operations.
An alternative to using the cipher and signature operations in the IBMJCEHYBRID
provider would be to extract IBMJCE or IBMJCECCA implementations from the HybridRACFPrivateKey
and use that implementation with the IBMJCE or IBMJCECCA providers. The HybridRACFPrivateKey
key implementations that are returned from the JCEHYBRIDRACFKS keystore can potentially
contain both the IBMJCE and IBMJCECCA representations of the same key. A user may decide
to fetch one or the other representation for use with the IBMJCE or IBMJCECCA providers respectively. For
example the following code snippet extracts the IBMJCE representation of the HybridRACFPrivateKey
and uses IBMJCE to encrypt and decrypt a piece of data.
When a user calls the store()
method of the JCEHYBRIDRACFKS
keystore the code will attempt to write all entries back out to the specified
SAF keyring. All entries with keys derived from IBMJCE will be stored as if
inserted from a JCERACFKS KeyStore. All entries with keys derived from
IBMJCECCA will be stored as if inserted from a JCECCARACFKS KeyStore.
A URL handler exists to allow the URL class to open the JCEHYBRIDRACFKS keystore. To make use of this new URL handler the caller must specify the following java environment variable.
The same syntax is used to specify the keyring and userid as used with a JCERACFKS or JCECCARACFKS keystore. For example
See additional information regarding the IBMJCEHYBRIDRACF keystore and key objects in the IBMJCEHYBRID provider javadoc by referencing the following classes
Copyright © 2010-2016 IBM Corporation, Inc. All Rights Reserved. |