Mar 20 ’13
Using Crypto Hardware With Java in Linux on System z
Cryptography can take many forms. It can be used to protect data in flight or data at rest, to authenticate a user, or provide a digital signature for banking or finance applications. Cryptography provides the building blocks applications use to protect the intellectual property that differentiates one customer from another.
Over the years, as Linux on System z has taken on a strong leadership role with Web- and Internet-facing applications, the value of Java and access to cryptography from Java has become paramount. Since Java is the most widely used language for Web applications, these applications have assumed the roles of protecting the confidentiality and integrity of data in the enterprise and the authentication of users and their authorization to various functions or data.
Hardware cryptography available on System z brings added business value to Java applications when running on Linux. The Crypto Express3 or Crypto Express4 cards in accelerator mode can provide cost-saving offload options, freeing up the processor to do other work as well as yielding drastic improvements in speed. The Central Processor Assist for Cryptographic Function (CPACF) capabilities, also available to Java applications, provide additional savings in processing time, which means better overall application throughput and cost savings. Banks and financial institutions can take advantage of the robust secure key and banking functions available on the Crypto Express3 and Crypto Express4 cards in coprocessor mode.
Writing a Java program that uses cryptographic functions from a library that exploits the System z cryptographic hardware can seem complex. It involves several components that must work together: the Linux kernel with a crypto device driver, System z-specific crypto libraries, openCryptoki with specific tokens, the Java Cryptography Architecture (JCA) with the Java Cryptography Extension (JCE) Application Program Interface (API) and the appropriate Java provider.
Here we demonstrate how to set up Linux on System z for an application to exploit cryptographic hardware features of the System z architecture using a simple Java program for encrypting and decrypting a message using the Advanced Encryption Standard (AES). However, let’s first briefly describe the cryptographic hardware features supported by the System z platform and the software stack needed to exploit these features in a Java program.
System z Cryptographic Hardware
The System z architecture provides CPACF on its processors, which is a free installation option for all System z servers in countries that aren’t subject to U.S. export regulations for cryptography. CPACF provides instructions that compute hash functions (SHA-1, SHA-224, SHA-256, SHA-386 and SHA-512), cryptographic functions to encrypt or decrypt messages using Data Encryption Standard (DES), triple DES, AES-128, AES-192 and AES-256 using several modes of operations (ECB, CBC, CFB, OFB, CTR, XTS, CCM and GCM), support for message authentication codes such as CBC-MAC, CMAC and GMAC, and a pseudo random generator. Depending on the size of the message to be encrypted, some modes of operation implemented in CPACF are more than 10 times faster than software implementations.
Crypto Express Adapters support offloading cryptographic functions to an adapter card, freeing the CPUs to perform other work. Linux can exploit Crypto Express Adapters both in accelerator mode, identified as CEX2A, CEX3A and CEX4A, and coprocessor mode, identified as CEX2C, CEX3C and CEX4C. Crypto Express Adapters in accelerator mode and coprocessor mode provide functions for RSA clear key encryption and decryption with the accelerators, providing better performance than the coprocessors. In addition, the Crypto Express coprocessors provide a true random number generator and functions for secure key cryptography, according to the Common Cryptographic Architecture (CCA).
With clear key cryptography, cryptographic keys are stored in memory. With secure key cryptography, all keys stored in memory are encrypted. These keys can only be decrypted and used to encrypt or decrypt messages inside a tamper-proof Hardware Security Module (HSM) such as the Crypto Express coprocessors. It can be addressed using an API defined in the CCA. Figure 1 shows the use of both clear key and secure key cryptography.
The Linux Crypto Software Stack
The crypto software stack in this example is required for a Java application to exploit cryptographic hardware; it consists of three layers:
• A Java layer, the JCA
• A PKCS#11 layer provided by openCryptoki on Linux
• Platform-specific libraries that exploit hardware-specific functions.
The JCA is a plug-in framework that supports registration of multiple providers of cryptographic functions. This lets a program use a cryptographic function from any of the installed providers that support the required function. The provider to be used can either be selected explicitly by the program or automatically, according to a priority assigned to the providers when configured. The JCE is an API for such a JCA provider. The IBMJCE provider is a software implementation of the JCE. Alternatively, the IBMPKCS11Impl provider is an implementation of JCE that calls a function from a library implementing the PKCS#11 standard.
The PKCS#11 standard describes a plug-in framework to address cryptographic functions implemented in hardware; it’s designed to provide a set of slots into which different tokens can be inserted. (To learn more about PKCS #11, the cryptographic token interface standard, see www.rsa.com/rsalabs/node.asp?id=2133.) The terminology, initially developed for smart cards, refers to them as tokens and to the smart card readers as slots. Implementation-wise, a slot is just an identifier (i.e., a small number) and a token is a library providing access to specific cryptographic hardware.
OpenCryptoki is an open source implementation of the PKCS#11 standard. OpenCryptoki comes with two System z-specific tokens, the icatoken for clear key cryptography, which calls the libica library, and the ccatoken for secure key cryptography, which calls the libcsulcca library. In addition, there’s a softtoken that provides software implementations of cryptographic functions and is mainly intended for testing openCryptoki.
The libica library provides an API to access the hash and clear key cryptographic functions available via the CPACF and the clear key RSA functions available from the Crypto Express adapters. The libcsulcca library implements an API for CCA and accommodates secure key cryptography functions provided by Crypto Express coprocessors. To access the Crypto Express adapters, you must install the z90crypt Linux kernel module.
A Simple Java Program
The simple Java program, Encrypt0.java (see Figure 2), can be used to demonstrate how to configure the software stack to exploit System z crypto hardware. This program generates a random AES key and AES cipher object. The AES cipher object is initialized for encryption with the generated key and is used to encrypt a plain text message constant. The AES cipher object is then reinitialized for decryption with the generated key and used to decrypt the cipher text that resulted from the previous encryption. The program outputs the initial plain text, the encrypted plain text and the result of decrypting the encrypted plain text as integer encoded bytes.
The program uses the JCE API to access cryptographic functions and runs on every system because all the needed cryptographic functions are implemented in the IBM JCE provider. To run the program, the source code must first be compiled with:
# javac Encrypt0.java
Then the program can be started with the code shown in Figure 3. The second line of the output, which shows the encrypted message, should look different for every call of the program because it depends on the key that’s randomly generated. The first line, the initial plain text, and the last line, the decrypted cipher text, will look the same.
Enabling Clear Key Encryption With Hardware
To enable use of cryptographic hardware, you must complete some installation and configuration steps as a super user (root).
First, you must install the libica and opencryptoki packages, both available in the Red Hat Enterprise Linux (RHEL) 6.2 and Novell’s SUSE Linux Enterprise Server (SLES) 11 SP2 distributions. These packages aren’t always installed by default; you may need to install the packages explicitly. The version of libica should be 2.0 or higher and openCryptoki should be 2.4.0 or later.
If the system has access to a crypto adapter, you must load the device driver for the crypto adapter into the kernel (on RHEL 6.2 and SLES11 SP2 using the modprobe z90crypt command) to enable offloading RSA functions.
Once you’ve installed the libica and openCryptoki packages, you must initialize and configure openCryptoki by running the pkcs11_startup command, which detects and configures the tokens available on the system. Next, you must start the daemon that manages tokens and slots with the pkcsslotd command.
Upon successful completion, you can use the pkcsconf tool to get information about openCryptoki (using the -i option) and find out which slots contain which tokens (with the -s option). In the output of pkcsconf –s, the section of the icatoken slot has the string “(ICA)” in the description attribute.
Assuming the slot number of the icatoken is 0, take the following steps to initialize the icatoken:
First, change the pin of the Security Officer (SO) of the token in slot 0 from the default “87654321” to another value:
# pkcsconf -P -c0
Next, set the label of the token in slot 0 to an arbitrary string (e.g., to “icatoken”):
# pkcsconf -I -c0
Then you must set the user pin of the token in slot 0:
# pkcsconf -u -c0
Now the icatoken is ready for use via openCryptoki.
Next, you must configure the JCA IBMPKCS11Impl provider to use openCryptoki. You need to create an IBMPKCS11Impl configuration file to tell IBMPKCS11Impl where to find the PKCS#11 implementation and what slot to use. Figure 4 shows the format of this file, which may be saved under an arbitrary path name (e.g., to /root/zpkcs.cfg).
Configure JCA to use specific providers. Locate the java.security file:
# find / -name java.security
There may be more than one, so choosing the java.security file of the Java installation being used is critical. To keep the example as simple as possible, JCA was configured to work with only two providers, the IBMPKCS11Impl provider as the primary provider and the IBMJCE provider as the fallback for all cryptographic functions not supported by IBMPKCS11Impl and openCryptoki with the icatoken. The icatoken itself provides all the cryptographic functions called in the sample program. However, when opening crypto libraries such as IBMPKCS11Impl, Java by itself requires some cryptographic functions not explicitly called in the sample program. For that reason, some mechanisms such as CKM_SHA1 are excluded from use with the IBMPKCS11Impl provider. For more complex applications, you may need to exclude additional mechanisms.
You must edit the java.security file so it only supports the IBMPKCS11Impl and IBMJCE providers. You can do this by deleting all the security provider definitions and adding the two lines with provider information shown in Figure 5.
You may need to replace the file name, /root/zpkcs.cfg, with the name chosen for IBMPKCS11Impl configuration file on the target system. Each security provider definition must be on its own line. Java isn’t forgiving when unexpected line breaks appear or line breaks are missing.
Programs that use openCryptoki should be a member of the UNIX group pkcs11. A user must be a member of this group to run the sample program. The program should now use the CPACF functions for AES encryption and decryption, via openCryptoki, with the icatoken and libica.
You can use the icastats command to verify that the hardware was accessed. When using icastats, note that libica writes usage counters for its cryptographic functions into a shared memory segment. This shared memory segment only exists as long as one or more processes are using libica. A trick to prevent the shared memory segment from being deleted after the program ends is to start a long-running process using libica (e.g., openssl speed with the ibmca engine enabled) and suspend the process with ctrl-z.
Cryptographic Hardware for Secure Key Encryption
To use secure key cryptography, a Crypto Express coprocessor must be online in the Linux image. You must insert the device driver for crypto adapters into the kernel with the modprobe z90crypt command. You can use the lszcrypt tool to check whether a coprocessor is available. The CCA library must then be installed. It isn’t part of any distribution, but you can download for free the RPM Package Manager (RPM) containing the library, along with some tools at www-03.ibm.com/security/cryptocards/. Once you’ve installed the CCA RPM, set the master key on the coprocessor. You can do this either with the Trusted Key Entry (TKE) console or the panel.exe tool included in the RPM. (For information on how to install CCA and set the master key on a crypto adapter with the panel.exe tool, refer to “Secure Key Solution with the Common Cryptographic Architecture Application Programmer's Guide,” online at www-03.ibm.com/security/cryptocards/pciecc/pdf/SC33-8294-03.pdf.)
Once this is done, you must set up openCryptoki by rerunning pkcs11_startup to discover the CCA library. Once the slot containing the CCA token is located, set its SO pin, user pin and label. Finally, you will need to modify the configuration file of the IBMPKCS11Impl provider to refer to the slot that contains the CCA token.
If the sample program is rerun, the AES functions from the CCA library are used, resulting in requests to the Crypto Express coprocessor. Issuing the lszcrypt command with the verbose option (-VV) will verify that requests are issued by the Java program and serviced by the crypto hardware.
Instead of using CCA via the standard JCA/JCE interface, you could use the Java Native Interface (JNI) that comes with CCA. This proprietary IBM interface provides a Java API to the CCA functions needed by many financial institutions. An introduction on how to use this interface can be found in the article “Secure Key Cryptography,” which appeared in the June/July 2008 issue of z/Journal (available at http://esmpubs.com/a0yf6).
Explicit Provider Selection
So far, the JCA has selected the best provider based on the priority defined for the providers in the java.security file. Alternatively, a programmer can specify a specific provider for all objects JCA providers implement. To do this, you must add the provider name as an argument to the getInstance() method in the program. For the IBMPKCS11Impl provider, the optional provider argument starts with the string, “IBMPKCS11Impl-” followed by the name attribute from the IBMPKCS11Impl configuration file. For the earlier example, a call to Cipher.getInstance() with explicit provider specification would look like:
Now the getInstance() method will always use the implementation provided by the IBMPKCS11Impl provider—using the token in the slot defined in the configuration file specified in java.security.
Using Persistent Objects in openCryptoki Tokens
Some applications require storing persistent objects (e.g., keys) in cryptographic tokens. A user pin is used to secure these objects from unauthorized use. This pin is chosen during openCryptoki token initialization. A Java program that needs to access a persistent token must log-in to the token (see Figure 6). The nullprompter function used appears on developerWorks at www.ibm.com/developerworks/java/jdk/security/60/secguides/pkcs11implDocs/IBMJavaPKCS11/ImplementationProvider.html.
If the token stores objects persistently, existing software using a software provider for the JCE API may not simply be reconfigured to use the IBMPKCS11Imp provider. The program may need some small code changes to allow a pin to be entered with a log-in to the token.
The Java Cryptography Architecture provides a flexible framework to support multiple implementations of cryptographic algorithms. This framework lets you plug in a PKCS#11 API to access hardware cryptographic implementations. You can then use a simple program to configure Java to access System z cryptographic hardware via the IBMPKCS11Impl provider and openCryptoki. Once the Java code accesses openCryptoki using either clear key or secure key cryptography, it’s a simple matter of redirecting IBMPKCS11Impl request to a specific slot. This will bring the speed and offloading advantages of hardware cryptography to the world of Java applications.