IBM CCA Key Wrapping Details - Part 1: Fixed-length Symmetric Key Tokens

IBM CCA Key Wrapping Details - Part 1: Fixed-length Symmetric Key Tokens

The IBM Common Cryptographic Architecture (CCA) API deals with keys, primarily in the form of key tokens, which may be stored in a Key Data Set (e.g. CKDS) under a "label" or held in memory.

The key value which is stored in such a token may be "in the clear", or encrypted using the applicable master key or a key-encrypting key (KEK), or a derivative thereof (as you will see). Master keys are loaded into the IBM cryptocard(s), away from prying eyes. Using the cryptography parlance, a key value is "wrapped" before being placed in an encrypted key token. The wrapping process is more complex than simple encryption of the clear key value using the master key.

The purpose of wrapping the key value is to:

  • protect the key value from exposure (simple encryption under a master key or derivative goes a long way towards achieving this)

  • ensure the key is only used for its intended purpose (so-called key separation)

  • allow verification of the integrity of the key token (not just the key value)

  • obfuscate the length (or strength) of the key.

Except where the length of the key is being obfuscated, the wrapping process does not significantly increase the space required to store the key. Typically, the wrapped key is the same size as the clear key.

Motivation

These days, I'm spending a lot of time working with customers on various projects involving cryptography, typically where more than one Hardware Security Module (HSM) vendor is in play. In this scenario, I need a firm handle on how keys might be transported and shared between HSMs, which in the IBM CCA context, means understanding key tokens and key wrapping with some precision.

Having said that, the intent of this article is educational (for me and the reader). You should always use the IBM CCA API to manipulate keys and key tokens. I provide a lot of detail in this series of articles, and I have gone to some lengths to ensure the information is accurate at the time of writing. However, my understanding of the key wrapping process may not be complete. Manual wrapping and unwrapping of keys, for any purpose other than education, is strongly discouraged.

There is an adage in the cryptography world that the privacy of encrypted material depends on the secrecy of the key used to encrypt it, not the secrecy of the algorithm. In this context, although I will give you the recipe to wrap and unwrap keys, you will need to know the clear value of your master keys and/or KEKs, if you want to play along in your own environment. Do not expose production master keys or KEKs as clear values.

Finally, I have discovered and verified the key wrapping process under z/OS and I provide some sample code in REXX. I have no reason to suspect there are any material differences in the CCA key wrapping process on distributed platforms, but I have not verified this.

CCA Key Token Varieties

IBM CCA has been around for decades. Over the years, as algorithms (and attacks) have emerged, requirements have driven an evolution of key token formats to the point now where more than a dozen distinct key token formats and wrapping methods exist. However, in my experience, the vast bulk of key tokens in use are fixed-length DES tokens. Yes, the world is moving to AES for symmetric cryptography, but progress is slow. These fixed-length tokens are the smallest, oldest and simplest methods of key storage in the CCA world, so they make a good place to start. I will describe fixed-length AES tokens in this article, and move to variable-length symmetric and asymmetric key tokens and key wrapping in subsequent articles.

Anatomy of the DES Fixed-Length Key Token

IBM does document the layout of all key token varieties in detail. The DES fixed-length token format is described here: https://www.ibm.com/docs/en/zos/3.1.0?topic=tokens-des-fixed-length-key-token

Let me pick out a few elements of the key token that are pertinent to the key wrapping process.

The first byte of the token identifies the token as internal (x'01') or external (x'02'). An internal token is used to perform cryptographic operations. An external token is used to hold a key that is being imported or exported from the local CCA environment to another CCA or non-CCA environment. From the point of view of understanding how keys are wrapped, we can consider internal and external tokens as essentially the same thing - only the key used to encrypt the key value is different: the DES master key (DES-MK) for internal tokens and a KEK for an external token. Note that a KEK is stored in an internal key token before it can be used to import/export other keys.

As you might expect, the key token has three 8-byte fields to hold the components of a single-length, double-length or triple-length DES key. I will denote these encrypted key components by KA, KB and KC. I will denote the corresponding clear key components PA, PB and PC, respectively.

To enforce key separation, the key token holds two 8-byte control vector fields, which I will denote by CVL (i.e. left) and CVR (i.e. right). In the early days of CCA, only single-length and double-length DES keys were contemplated. CVL and CVR hold essentially the same information about how the key is to be used, but they differ in 3 key form bits (see: https://www.ibm.com/docs/en/zos/3.1.0?topic=table-key-form-bits-fff ). Note that CVR is set to nulls for a single-length key (except for WRAPENH3 wrapping - see below). Note also that an old-fashioned DATA key token (which is only used for raw encryption and decryption) has CVL=nulls and CVR=nulls. I'm not going to venture into all the considerations around control vectors. Suffice to say that they play a role in key wrapping, which I will describe in detail.

WRAP-ECB

The oldest and simplest method of key wrapping is called WRAP-ECB. This is the default wrapping for single and double-length keys. It is not used for triple-length keys, as a rule.

Henceforth, I won't distinguish between the DES-MK for internal tokens and a KEK for external tokens - I will simply refer to a KEK, which is used to wrap the key value stored in the token. The KEK can be a double or triple-length key.

WRAP-ECB wraps the left half of the clear key, PA, and the right half, PB, separately. The key which encrypts PA, denoted by KEKA, is formed by computing the bitwise exclusive OR (XOR) of the KEK with 2 or 3 copies of CVL, depending on the length of the KEK. The key which encrypts PB, denoted by KEKB, is formed the same way, using copies of CVR. When wrapping a single-length key, KB is nulls.

If I use eECB(K, D) to denote DES encryption, in ECB mode, of data, D, using key, K, and I use || to denote concatenation, then I can express the WRAP-ECB wrapping process as follows:

Let's work through a couple of examples.

First, let's export an internal double-length OPINENC key, K, (used in payment card transactions to encrypt PIN blocks), with a known key value, using an EXPORTER key (again with known value) as our KEK:

Now let's try unwrapping the key in the internal token for our OPINENC key. This time, the KEK is the DES-MK loaded into the cryptocard(s). dECB(K, D) denotes DES decryption in ECB mode of data, D, using key, K.

WRAP-ENH

Over time, various potential vulnerabilities in the WRAP-ECB wrapping technique have come to light. Accordingly, IBM introduced an enhanced wrapping method denoted by WRAP-ENH, for single and double-length keys which:

  • Uses a key derived from the KEK using a secure one-way HMAC algorithm

  • Binds the two halves of a double-length key together.

For any crypto-nerds who want to understand the vulnerabilities of WRAP-ECB and how these enhanced countermeasures might strengthen key token security, I refer you to the PhD thesis of Michael Bond from 2004 (see: https://www.mike-bond.com/research/Thesis.pdf ).

Anyway, for the rest of us, I will present the steps of the enhanced wrapping process with a focus on what to do, rather than why we are doing it. We will wrap our OPINENC key (above), using the DES-MK, as we go.

Extending the KEK

The first step is to extend the KEK to be a triple-length key, if necessary, by repeating the first 8 bytes of a double-length KEK at the end of the key. Using our DES-MK from above,

Deriving the Wrapping Key (WK)

The WK is derived from the KEK using the KDF in Counter Mode algorithm described in NIST Special Publication 800-38D (see: https://csrc.nist.gov/pubs/sp/800/38/d/final ) using HMAC with SHA-256 hash as the Pseudo-Random Function (PRF) used by the Key Derivation Function (KDF).

The HMAC message authentication algorithm (see: https://en.wikipedia.org/wiki/HMAC ), using our extended KEK as the key and SHA-256 (see: https://en.wikipedia.org/wiki/SHA-2 ) as the hash function, produces a 32-byte authentication code as output. We take the first 24 bytes of this output as our derived key.

The HMAC algorithm requires a message as input to compute the corresponding authentication code. For the WRAP-ENH wrapping method, this message is (using the notation of NIST 800-38D):

Note that the label corresponds to the string ENHANCEDWRAP2010 in ASCII.

I know what you are thinking... This is all very nice, but how do I compute a HMAC with SHA-256 hash? Well, you use the IBM CCA API, of course! Here's an example of a REXX script to compute a HMAC given a specified key and message. This script calls CSNBKTB2 (see: https://www.ibm.com/docs/en/zos/3.1.0?topic=keys-key-token-build2-csnbktb2-csnektb2 ) to build a clear HMAC token, then calls CSNBHMG (see: https://www.ibm.com/docs/en/zos/3.1.0?topic=messages-hmac-generate-csnbhmg-csnbhmg1-csnehmg-csnehmg1 ) to compute the HMAC authentication code:

At this point, let me pause for a message from our sponsor (me)...

As elegant as this REXX code is, it is a bit verbose. By way of comparison, this is the equivalent script written using my ZCCREXX productivity tool (see: https://github.com/admattingly/ZCCREXX ):

Either way, the output is the same:

Apply Control Vector

Now we create a variant of the WK by performing a bitwise exclusive OR with three copies of the left control vector:

Wrap a Single-Length Key

If the key to be wrapped is a single-length DES key, we simply encrypt the clear key value using our WK:

Wrap a Double-Length Key

If the key to be wrapped is a double-length key, something very interesting happens - we bind or chain the two halves of the key together. Without going into the why, this thwarts a variety of potential attacks.

Here's the recipe:

  • compute SHA-1 hash (see: https://en.wikipedia.org/wiki/SHA-1 ) of PB

  • XOR PA with first 8 bytes of this 20-byte hash

  • concatenate the result of the XOR and (unmodified) PB to form a 16-byte value

  • Encrypt this value, in CBC mode (starting with an initialization vector of all nulls) to form the 16-byte wrapped key.

I have assumed to this point that the reader is familiar with symmetric encryption and its various modes. If you are a bit rusty with this stuff (see: https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation ), the essential difference between ECB mode and CBC mode is that ECB mode encrypts each 8-byte block of plaintext independently (i.e. the ciphertext depends only on the key), whereas CBC mode uses the ciphertext from the previous block as input to the encryption of the next block. So by making recovery of PA dependent on knowledge of PB, and using CBC (left-to-right, dependent mode of encryption) we have locked the two halves of the key together - they must be wrapped and unwrapped as a single unit.

Using eCBC(K, D) to denote DES encryption in CBC mode of data, D, using key, K, we have:

WRAPENH2

To wrap a triple-length key, WRAP-ECB and WRAP-ENH are not fit for purpose. WRAPENH2 is a fairly straightforward extension of WRAP-ENH, with a couple of minor adjustments.

The key derivation process is identical, except the application of the control vector variant will necessarily produce a slightly different derived key because the control vector has different key form bits (to indicate it is a triple-length key) and the ENH-ONLY bit is set in both control vectorts, since a triple-length key cannot be re-wrapped using WRAP-ECB.

Essentially, if we are using the correct control vector, we get the right derived key, using the same process as WRAP-ENH.

Key Part Chaining

The key component chaining process for WRAPENH2 is necessarily different to WRAP-ENH because we have three key components to chain, instead of two.

The other slight wrinkle is that by the time WRAPENH2 came along, concerns were emerging about the security of SHA-1 as a hashing scheme, so SHA-256 took its place in the chaining process.

Let's work through an example by adding a third component to our previous clear key:

Now we form our derived key, WK, as before, noting the slightly different CVL for a triple-length OPINENC key:

Finally, encrypt the chained payload, PD, using key, WK, in CBC mode:

WRAPENH3

At this point, everything in the CCA world was sailing along nicely. All tastes were catered for, in terms of key length/strength. Key component chaining added robustness to key wrapping. What could possibly go wrong?

Enter the payment card regulator, PCI, with new requirements for key wrapping (see: https://community.ibm.com/community/user/ibmz-and-linuxone/blogs/richard-kisley1/2021/05/21/ibm-tdes-key-token-wrapenh3-for-pci-pin?communityKey=6593e27b-caf6-4f6c-a8a8-10b62a02509c for a comprehensive discussion). In a nutshell, two requirements were imposed:

  • The key token must include a secure authentication code to provide a means of detecting unauthorised modifications to the token, not just the key material.

  • The length of the wrapped key must be obfuscated to prevent an attacker being able to identify, for example, the shorter/weaker keys in a CKDS and focus their key-breaking efforts on those soft targets.

Derived Keys

For WRAPENH3, we derive two keys - one for wrapping our key and the other for computing a TDES-CMAC of the key token to generate an authentication code. KDF in Counter Mode is deployed using HMAC with SHA-256 as the PRF, as before. What changes is the label component of the message used in generating the derived keys.

For the wrapping key, a label of "WRAPENH3KEY-ENCR" (in ASCII) is used.

For the TDES-CMAC key, a label of "WRAPENH3KEY-CMAC" (in ASCII) is used.

Let's derive the wrapping key corresponding to our DES-MK as the KEK, by extending this key to triple-length, as before, then constructing a message with the appropriate label and computing the HMAC with SHA-256:

Now repeat the process to derive our TDES-CMAC key, CK:

PCI has deprecated the use of variant schemes, like "XOR with control vector", so the WK and CK are used unaltered.

Key Extension

To obfuscate the key length, the clear key is extended with nulls to 24-bytes, then chained in the same way as for WRAPENH2.

For example, extending and chaining our original double-length key:

Now we use the WK to wrap the PD (chained 24-byte key) as before:

Authentication Code

To compute the authentication code, we construct a modified version of the 64-byte key token as the message, as follows:

  • Bytes  0-15 are copied from the original token

  • Bytes 16-31 are replaced with PA || PB (PB = nulls for a single-length key)

  • Bytes 32-39 are copied from the original token

  • Bytes 40-47 are nulls

  • Bytes 48-55 are replaced with PC (PC= nulls for a single- or double-length key)

  • Bytes 56-59 are copied from the original token

  • Bytes 60-63 are nulls

To illustrate, let's take the encrypted internal key token for our double-length OPINENC key and modify it according to these specifications:

Note: The key token contains no indicators of the length of the key. The CVL's key form bits indicate a triple-length key, irrespective of the actual length of the key. This is to keep PCI happy.

We compute the TDES-CMAC of this message, using CK as the key, which yields:

When an encrypted token is constructed by CCA, this authentication code is placed in the CVR field of the token (see bytes 40-47 of the above token).

At the time of writing, I have covered all the wrapping schemes for fixed-length DES key tokens. I don't expect any more to emerge, as the world seems to be moving away from proprietary key tokens and wrapping schemes, in favour of things like TR-31 (more on that in a subsequent article) and as already noted, DES is giving way to AES as the symmetric encryption algorithm of choice.

AES Fixed-Length Internal Key Tokens

Relax! There is only one wrapping scheme for AES fixed-length internal tokens. These tokens hold AES DATA keys only (see: https://www.ibm.com/docs/en/zos/3.1.0?topic=tokens-aes-internal-fixed-length-key-token ). They have no mechanism to enforce key separation. They can only be used to perform raw AES encryption and decryption. AES variable-length key tokens (discussed in a future article) are the real deal, with key separation, sophisticated wrapping and other features that comply with the abovementioned PCI requirements.

The key in an AES fixed-length token is wrapped by extending the key with nulls out to a 256-bit (32-byte) value, then encrypting the extended key using the AES-MK in CBC mode. That's all there is to it.

Here's a worked example, where aeCBC(K, D) denotes AES encryption of data, D, using key, K, in CBC mode:

That was easy, wasn't it?

One More Thing...

There is one more fixed-length key token I haven't mentioned, the External RKX DES key token. I might come back to this one in a future article, once I've discussed asymmetric key formats and wrapping - it will make more sense then.

Acknowledgements

I must express my appreciation to Eric Rossman and Richard Kisley for their kind assistance.

🎶Marvin Malcolm

Improving digital healthcare for all Australians, while sharing great music across the airwaves 🎶📻

9mo

Interesting. Nice to see you still carrying the “z” flag Andrew.

Like
Reply

To view or add a comment, sign in

Others also viewed

Explore topics