Navigate

Upgrade safe JCE deployment for Java on RHEL

As computers get faster and faster the standard approaches to security have become less and less effective at thwarting the variety of attacks we are likely, or–in some cases–unlikely to face. Unfortunately, in response to these advances our best response to date has been to up the ceiling on our current standard approaches at securing data. This usually means using encryption algorithms with larger and larger key sizes. If you are a Java developer or Java application administrator this means you are more likely than ever to encounter situations where the standard encryption algorithms in your JDK are inadequate to meet your business needs.
Due to import control restrictions the standard encryption shipped with most Java implementations is limited. The maximum key sizes allowed by the default “strong” jurisdiction policy files is 128 bits. If you try and use an encryption key with anything larger you are likely to encounter an InvalidKeyException due to an Illegal key size. In order to work around this issue it is generally necessary to agree to not violate export regulations before you can then download the Java Cryptography Extension (JCE) for your JDK and install it.

It’s a very simple matter for most people to download and update their Java environment with the “unlimited” strength policy files. According to the README file contained in the download simply backup your current local_policy.jar and US_export_policy.jar located in/lib/security and replace them with the unlimited strength versions contained in the download.

However, if you inspect these files on a typical Red Hat system using the Sun Java packages provided by Red Hat you will most likely find they are a symlinks to /etc/alternatives. One could easily ignore this and clobber the target files with the JCE replacement files, and it will most likely work–at least until the next Java update. A cleaner solution is to leverage the alternatives framework to provide an upgrade safe deployment of the JCE policy files.

First you need to ensure you are using the Java packages provided by Red Hat. If you are a paying RHEL subscriber there’s no reason you shouldn’t be using them. They are in the RHEL Supplementary channel in RHN. You should see “rhel-x86_64-server-supplementary-5” or something similar depending on your release and architecture listed when you issue a yum repolist command. If your system is not currently subscribed to the Supplementary channel  you will need to add the channel to the system in RHN, Satellite server, or from the command line using rhn-channel –add.

Red Hat provides JRE/JDK packages and support for both Sun/Oracle and IBM. This command will provide a complete listing of all the Java packages currently installed and/or available to your system:
$ sudo yum list java*

For Sun Java 6 you would need one or more of the following packages:
java-1.6.0-sun.i586
java-1.6.0-sun.x86_64
java-1.6.0-sun-devel.i586
java-1.6.0-sun-devel.x86_64

The -devel packages are for the full JDK which can be ignored if you only need a Java Runtime Environment. Technically the policy files are not 32 or 64 bit specific, but the RPM packages duplicate them to avoid file conflicts. However, we can easily support both a 32 bit and a 64 bit JRE with a single copy of the JCE files which can be download from Oracle:
http://www.oracle.com/technetwork/java/javase/downloads/jce-6-download-429243.html

Rather than place them in the “typical” location under /lib/security we’re going to create a new location similar to where the Red Hat RPM’s place them:
$ sudo mkdir -p /usr/lib/jvm-private/sun/jce/unlimited

Copy or move local_policy.jar and US_export_policy.jar from the zip download into this location. If you issue a tree command on /usr/lib/jvm-private/ it should look something similar to the following if you have both the 32 and 64 bit JRE installed, but only one or the other is required.

$ tree /usr/lib/jvm-private/
/usr/lib/jvm-private/
├── java-1.6.0-sun
│   └── jce
│       └── vanilla
│           ├── local_policy.jar
│           └── US_export_policy.jar
├── java-1.6.0-sun.x86_64
│   └── jce
│       └── vanilla
│           ├── local_policy.jar
│           └── US_export_policy.jar
└── sun
└── jce
└── unlimited
├── local_policy.jar
└── US_export_policy.jar

Now simply issue one or both of the following commands depending on if you have the 32 bit or 64 bit JRE installed.

32 bit:
update-alternatives
–install
/usr/lib/jvm/jre-1.6.0-sun/lib/security/local_policy.jar
jce_1.6.0_sun_local_policy
/usr/lib/jvm-private/sun/jce/unlimited/local_policy.jar
900000
–slave
/usr/lib/jvm/jre-1.6.0-sun/lib/security/US_export_policy.jar
jce_1.6.0_sun_us_export_policy
/usr/lib/jvm-private/sun/jce/unlimited/US_export_policy.jar

64 bit:
update-alternatives
–install
/usr/lib/jvm/jre-1.6.0-sun.x86_64/lib/security/local_policy.jar
jce_1.6.0_sun_local_policy.x86_64
/usr/lib/jvm-private/sun/jce/unlimited/local_policy.jar
900000
–slave
/usr/lib/jvm/jre-1.6.0-sun.x86_64/lib/security/US_export_policy.jar
jce_1.6.0_sun_us_export_policy.x86_64
/usr/lib/jvm-private/sun/jce/unlimited/US_export_policy.jar

As a final step you should confirm the jce symlinks under /etc/alternatives have been updated and point to your new policy files:
$ ls -l /etc/alternatives/jce*

If they don’t simply issue one or both of the following commands depending on your environment:
sudo alternatives –auto jce_1.6.0_sun_local_policy
sudo alternatives –auto jce_1.6.0_sun_local_policy.x86_64

To understand a bit more about how this works and why it provides an upgrade safe approach to the JCE policy files one can inspect the install scripts in the RPM packages. Simply issue a command similar to one of these depending on the exact version of your installed JRE:
$ rpm -q –scripts java-1.6.0-sun-1.6.0.33-1jpp.1.el5_8.x86_64
$ rpm -q –scripts java-1.6.0-sun-1.6.0.33-1jpp.1.el5_8.i586

You should see an update-alternatives statement similar to the ones above. A key difference aside from the path to the target files under /usr/lib/jvm-private is the priority number. Instead of 900000 there should be a number which corresponds to the JRE version. In the alternatives system the higher number takes precedence placing our custom deployment of the JCE policy files above and beyond any of the RPM package deployments. As updates of the JRE are pushed by Red Hat the unlimited JCE policy files should continue to be utilized by each subsequent upgrade. If you upgrade from Sun Java 6 to Sun Java 7 you will need to issue an update-alternatives command specific to Sun Java 7, but you can reuse the same unlimited JCE policy files.

The same approach will also work for the IBM JDK with only slight modifications.

It is, of course, necessary to download IBM’s Unrestricted JCE Policy files:
https://www14.software.ibm.com/webapp/iwm/web/preLogin.do?source=jcesdk

Create a home for the new files and place them there:
$ sudo mkdir -p /usr/lib/jvm-private/ibm/jce/unrestricted

The update-alternatives statements would look like the following.

32 bit:
update-alternatives
–install
/usr/lib/jvm/jre-1.6.0-ibm/lib/security/local_policy.jar
jce_1.6.0_ibm_local_policy
/usr/lib/jvm-private/ibm/jce/unrestricted/local_policy.jar
900000
–slave
/usr/lib/jvm/jre-1.6.0-ibm/lib/security/US_export_policy.jar
jce_1.6.0_ibm_us_export_policy
/usr/lib/jvm-private/ibm/jce/unrestricted/US_export_policy.jar

64 bit:
update-alternatives
–install
/usr/lib/jvm/jre-1.6.0-ibm.x86_64/lib/security/local_policy.jar
jce_1.6.0_ibm_local_policy.x86_64
/usr/lib/jvm-private/ibm/jce/unrestricted/local_policy.jar
900000
–slave
/usr/lib/jvm/jre-1.6.0-ibm.x86_64/lib/security/US_export_policy.jar
jce_1.6.0_ibm_us_export_policy.x86_64
/usr/lib/jvm-private/ibm/jce/unrestricted/US_export_policy.jar

Finally, you may have noticed I did not cover the OpenJDK. This is not because of some bias against the OpenJDK. On the contrary, if you can use the OpenJDK you should. As it turns out the OpenJDK is not encumbered by the same legal restrictions as Oracle and IBM:

“The JCE in OpenJDK has an open cryptographic interface, meaning it does not restrict which providers can be used. Compliance with United States export controls and with local law governing the import/export of products incorporating the JCE in the OpenJDK is the responsibility of the licensee.”
Reference:
http://openjdk.java.net/groups/security/

The result is one does not need to worry about downloading a separate JCE policy for the OpenJDK. It should work with higher encryption keys right out of the box.