ICSF return codes – not for humans

Below are some of the errors I experienced using ICSF

IEC143I 213-85 RC=X’00000008′,RSN=X’0000271C’

Colin’s answer.

It could not find the key. Perhaps the CKDS was updated using the KGUP utility. Try refreshing the CKDS (either in batch or using the ISPF panels). For example


Perhaps you are trying to encrypt a data set with a non symmetric key – for example a PKI.b

IEC143I 213-8,RC=X’00000008′,RSN=X’00000BF3′

BF3 (3059) The provided key_identifier refers to an encrypted variable-length CCA key token or a key label of an encrypted variable-length CCA key token. The key-management field in the CCA token does not allow its use in high performance encrypted key operations.

User action: Supply a key token or the label of a key token with the required key-management settings.

Colin’s comments

With CSNBKTB2 I got the 0xbf3 when ‘XPRTCPAC’ was missing. For example I needed rule_array = ‘INTERNAL’||’AES ‘||’CIPHER ‘||’ANY-MODE’||’XPRTCPAC’

The doc for AES CIPHER says XPRTCPAC Allow export to CPACF protected key format.

I also got this trying to use an EXPORTER or an IMPORTER key. This does not support XPRTCPAC.

IEC143I 213-85, RC=X’00000008′,RSN=X’00000BFB’

The provided symmetric key label refers to an encrypted CCA key token, and the CSFKEYS profile covering it does not allow its use in high performance encrypted key operations.

User action: Contact your ICSF or RACF administrator if you need to use this key in calls to Symmetric Key Encipher (CSNBSYE) or Symmetric Key Decipher (CSNBSYD). Otherwise, use Encipher (CSNBENC) or Decipher (CSNBDEC) instead.

Colin’s answer

Define the profile with the bold text


IEC143I 213-85, RC=X’00000008′,RSN=X’0000272C’

Colin’s comment

I got this when I tried to use


The following worked


UPDATE: AES256 is used for dataset encryption.



Colin’s comment

I was trying to use TRANSKEY but the length of the transkey is shorter than the key being defined, for example



IEC143I 213-86

During open processing for an encrypted extended format data set, on return from the ICSF service used to process the key label associated with the data set, the system detected that the encryption type of the data key associated with the key label was not of a supported encryption type. Only encryption keys of type AES256 are supported for extended format data sets.

Colin’s comment



with length(32) works. With length(16) it gives 213-86

Update: Only encryption keys of type AES256 are supported for ANY data set encryption.

IEC143I 213-85, RC=X’00000008′,RSN=X’0000085E’

The key usage attributes of the variable-length key token does not allow the requested operation. For example, the request might have been to encrypt data, but encryption is not allowed, or the request might have been to use the ECB cipher mode, but that mode is not allowed.
User action: Use the variable-length key token in a manner consistent with its usage attributes or create a new key token with the desired attributes

Colin’s comments 1

I got this when I had


Changing it to type(DATA) worked.

Colin’s comments 2

  • I had a C program and used CSNBKTB2. When CBC was defaulted I got the 85E, when I used ANY-MODE it worked.
  • I had another program which used rule_array = ‘INTERNAL’||’AES ‘||’CIPHER ‘||’XPRTCPAC’||’ANY-MODE’||’ENCRYPT ‘. Without ENCYPT it worked. With both ENCRYPT and DECRYPT it worked.

Return codes

048 ( 72 ) The value specified for length parameter for a key token, key, or text field is not valid.

Colin’s comments.

I got this in CSNDSYI2 when using a private key with a small key size(1024). When I used a private key with key size of 4096 it worked.

09B ( 155 ) The value that the generated_key_identifier parameter specifies is not valid,

or it is not consistent with the value that the key_form parameter specifies.

Colin’s comments

Case 1.

I was trying to generate an IMPORTER and an EXPORTER key. I used CSNBKTB2 to build a skeleton. When I used CSNBKGN2 to generate the token. I got this return code. I think this is because I did not provide a Transport Encryption Key (KEK)

When I used CSNDEDH passing the output from CSNBKTB2, the private key label, and the public key label, it worked, and I could add it to the CKDS using CSNBKRC2.

Case 2.

CSNBKGN2 only accepts skeletons created with type = CIPHER, HMAC, or MAC. See table 77. Trying to use a skeleton for EXPORTER or IMPORTER give you this message.

Case 3.

In CSNBKTB2 I had specified


CSNBKGN2 gave me rs 155. Remove the DECRYPT and it worked

F6 ( 246 ) Not documented

I got

  • CSNDKRC  add pkds getting 0 246

I got this with

rc = 'FFFFFFFF'x
rs = 'FFFFFFFF'x
  'myrc' 'myrs' ,

because I had not initialised myrc and myrs.

7FB ( 2040 ) Bad data

This check is based on the first byte in the key identifier parameter. The key identifier provided is either an
internal token, where an external or null token was required; or an external or null token, where an internal token was required. The token provided may be none of these, and, therefore, the parameter is not a key identifier at all.

Colin’s comment

  • Check you are passing in the right data! I had misspelt a variable.
  • I was trying to import a PKI public certificate – when it was an AES exported certificate
  • I was trying to use a PKI private certificate of type ECC. CSNDSYI2 only accepts … key enciphered under an RSA public key or AES EXPORTER key.
  • You are trying to use CSNDSYI2 for a DATA key when you should be using CSNDSYI.

806 ( 2054 ) Invalid RSA enciphered key cryptogram; OAEP optional encoding parameters failed validation.

Colin’s comments

I got this when I used the wrong private key to decrypt a key in CSNDSYI2. When I used the correct key it worked.

829 ( 2089 ) The algorithm does not match the algorithm of the key identifier

Colin’s comment.

  • I got this because I had a private key created as an ECC. Where it was expecting an RSA key.
  • CSNDSYX trying to use an PKI public key with ECC…. to encryption under an application supplied RSA public key or AES EXPORTER key.

86A ( 2154 ) Bad key type

At least one key token passed to this callable service does not have the required key type for the specified

Colin’s comments.

  • I got this trying to use an Importer key instead of an Exporter key.
  • I got this trying to use a DH key when an RSA key was expected. The requirements were CSNDSYX: RSA public key or AES EXPORTER

86E ( 2158 ) Not in the books

I got this doing Diffie-Hellman key exchange CSNDEDH using a private key and a public key.

  • With private ECC Curve: PRIME Bits 521 and public ECC Curve: PRIME Bits 384 I got reason code 2158.
  • With private ECC Curve: PRIME Bits 521 and public ECC Curve: PRIME Bits 521 I got reason code 0.
  • With private ECC Curve: PRIME Bits 521 and public ECC Curve: BRAINPOOL Bits 521 I got reason code 2158.
  • With private ECC Curve: BRAINPOOL Bits 521 and public ECC Curve: BRAINPOOL Bits 521 I got reason code 0.

It looks like you have to have matching curve type, and matching size (in bits) for it to work. The documentation under ECC Diffie-Hellman (CSNDEDH and CSNFEDH) says

The ECC curve type and size must be the same as the type (Prime, Brainpool, or Koblitz) and size of
the ECC key-token specified by the public key identifier parameter.

DC9 ( 3529 ) Bad label

A key identifier was supplied to a callable service as a key token or the label of a key token in a key data set. Either the key type of the key or the algorithm of the key is unsupported by the cryptographic features available to ICSF.

Colin’s comment

Perhaps you specified a label name – when it did not exit.

PKA Key Generate (CSNDPKG):generated_key_token_length: The length of the generated key token or label for the generated key token.

I assumed you could give it a label, and it would store the data under that label.

2B30 ( 11056 ) The input PKA token contains length fields that are not valid.

User action: Re-create the key token.

Colin’s comment
2B30 (11056) The skeleton_key_identifier_length field is not valid.
User action:  Check  the skeleton_key_identifier_length and skeleton_key_identifier  (returned from CSNDPKB fields key_token_length,key_token)

2AF8 ( 11000 ) The value specified for length parameter for a key token, key, or text field is not valid.

User action: Correct the appropriate length field parameter. For example I had target_key_identifier_length as 1000, but the documentation said The maximum value is 725 bytes.

Colin’s comment

Make sure you pass the address of the length eg &size, not the size itself.

Make sure you are adding to the correct database. If you try to add a PKI to a CKDS you will get this reason code.

Make fields bigger. I got this with

RSA_enciphered_key_length: The length of the RSA_enciphered_key parameter. This service updates this field with the actual length of the RSA_enciphered_key it generates. The maximum size is 512 bytes.

I had to make it 530 before it worked. Note when I came to check this at a later data – it all worked perfectly and I did not need to make it bigger!)

271C ( 10012 ) A key label was supplied for a key identifier parameter.

This label is the label of a key in the in-storage CKDS or PKDS. A key record with that label (and the specific type if required by the ICSF callable service) could not be found. For a retained key label, this error code is also returned if the key is not found in the CCA coprocessor specified in the PKDS record.

Colin’s comment.

  • I had specified a key of type data (which existed in the CKDS), but it was expecting a key of type Exporter, so was not found and could not find the label in the PKDS).
  • CSNDSYX trying to use an PKI public key with ECC…. to encryption under an application supplied RSA public key or AES EXPORTER key.
  • You specified a key, but the key was not char[64] and had garbage in the value. This can occur if you use a C null terminated string.

2740 ( 10048 ) The key_type parameter does not contain one of the valid types for the service or the keyword TOKEN.

Colin’s comment

I was trying to use CSNDEDH which required a private key and a public key of type ECC. I had specified an RSA key.

3E80(16000) RACF failed your request to use this service or PKCS #11 token. This may be caused by the CSFSERV or CRYPTOZ class.

Colin’s comments.

Check the job log. This userid does not have read access to CSFOWH CLASS(CSFSERV )

Can you send a secret to Mars?

I’ve been reading a book on cryptography, and playing with encryption of data between two sites, and these got me thinking about the history of cryptography.

Hundreds of years ago cryptography was used to send state secrets. With a lot of data, experts could crack and read your correspondence. You could have a “one time pad” where you used a key just once, which helped. The biggest problem was key distribution. In theory you could send the keys (or the pad of keys) through the post, but if people are intercepting and reading your mail – they get to see the keys!

With computers and mathematicians, sending keys to someone has got easier. It is harder to break, but not impossible.

I saw a document recently which said send your key on paper, in an envelope, by courier and not over the network. If people can read documents wrapped in jars from 2000 years ago in a CAT scanner – reading through an envelope should be easy. Also, there may be no rocket going to Mars to take your letter.

There are two common techniques used today for two ends to get a common secret: RSA and Diffie-Hellman


With RSA you have a private key (which only you has access to) and a public key – which every one can have access to. If you want to send me some data then you encrypt it with my public key and send the data to me. I use my private key and can then decrypt it.

Is this good enough ?

If you can afford to send someone to Mars, you can afford to have a team of programmers to create every possible private-public key combination and have a look up – if the public key is x then the private key is X. If you advertise a public key then some people can decrypt your message. If we do not advertise which private/public key to use then it makes it harder. But how do we negotiate in secret which private/public key to use?


From a mathematical perspective I found this is much more interesting. We want to communicate to get a secret key, knowing that people can monitor the network and see what we are sending.

It relies on some number theory properties

  • (x **a ) **b = (x**b) **a for example (a**2) **3 = (a* a*) * (a* a) * (a*a) = (a * a * a) * ( a * a * a) = (a**3) **2
  • modular arithmetic x mod y is the remainder if you divide x by y. 17 mod 5 is 2
  • combining these (x ** a) mod y = (x mod y ) **a mod y. x**a could have hundreds or millions of digits. “x mod y” is less than y, so may fit in 64 bit integers.
  • We agree two numbers x and y, which the spy can snoop. I think of a big number a, you think of a big number b.
  • I calculate (x **a) mod y = X and send it to you. You take X and calculate X ** b mod y.
  • You calculate x **b mod y = Y and send it to me. I take Y and calculate Y**a mod y
  • The two numbers are the same, and we can use it as our secret key. The secret agent who does not know a or b cannot calculate the secret.

The secret agents listening on the connection do not know which values of a and b we used, and there could be an infinite number of ‘a’s which all give the same value of (x **a) mod y. Typically people use a and b with thousands of digits.

If you have an x with thousands of digits, and an a with thousands of digits x **a will have millions of digits so you have to have special routines to do the calculations. Fortunately the mod y calculation reduces the size down to a more manageable number – with only thousands of digits.

Who said mathematics was boring?

Is this good enough ?

If you use small numbers then it is easy to crack. Today’s thinking is using more than 2048 bits will be hard to crack.

Backwards migration problem with load modules? – try using DLLs

I had a problem where I compiled a program on z/OS 2.4. When it ran on z/OS 2.3 it abended. This was because I had included some z/OS code with my load module, which was not compatible with back level versions of z/OS.
I didn’t have a z/OS 2.3 to run on …. what could I do? A quick search showed me that using DLL’s was the right answer. You may be using this today without knowing it, for example your C program does not contain the whole printf executable, it just contains a link to it.

What did I do?

My old JCL had


Where the INCLUDE GSK(..) copied in the (z/OS 2.4 specific ) code needed to execute.

My new JCL had

include /usr/lpp/gskssl/lib/GSKSSL.x
include /usr/lpp/gskssl/lib/GSKCMS31.x


How does it work?

The GSKSSL.x has

include /usr/lpp/gskssl/lib/GSKSSL.x
IMPORT CODE,’GSKSSL’,’gsk_attribute_get_buffer’
IMPORT CODE,’GSKSSL’,’gsk_attribute_get_cert_info’

This says gsk_attribute_get_buffer is in module GSKSSL, use dynamic resolve at execution time.

When the program is executed, the loader looks for entries which have pending dynamic resolve. In this case it sees gsk_attribute_get_buffer, It loads the module GSKSSL from the executing system, looks inside it, locates the gsk_attribute_get_buffer code and resolves the address.

On my z/OS 2.4 system it loaded the 2.4 version of GSKSSL, on the z/OS 2.3 system it loaded the 2.3 version of GSKSSL. As long as the parameters to the calls are consistent it will work.

Does this work for my own code?

Yes. You have to build it a certain way. Look for side-deck in the C user guide and C Programming guide.

Are there any other benefits?

Yes – your load modules are smaller, because the imported code is obtained at run time, and not included in your load module. Also, as Charles M. pointed out, another benefit is that you are no longer violating IBM’s license by shipping z/OS licensed code as part of your product.

What can I ship?

Charles Mills pointed me to this documented list of what you can do. See here under Redistribution of Code Routines. Which starts

This document includes information about certain callable service stub and linkage-assist (stub) routines and other routines that are contained in specific data sets and file system directories that are intended to be bound, link-edited, or otherwise included with code and run on z/OS systems. With your authorized use of z/OS, you can include these routines into your modules and distribute your
modules with the included routines for the purposes of developing, using, marketing, and distributing programs that conform to the documented programming interfaces for z/OS, provided that each routine is included in its entirety, including any IBM copyright statements.

It then goes on and lists which libraries you can use.

One Minute MVS – ICSF. It might be better if they finished it.

This is another post in the series of “One Minute MVS” which aims to give the basics you need to be able to get started with a topic.

The IBM documentation says: ICSF provides support for

  • The ANSI Data Encryption Algorithm (DES) and Advanced Encryption Standard (AES) encryption and decryption
  • DES key management and transport
  • AES key management and transport
  • Financial services including PINs, payment card industry transactions and ATMs
  • Public key operations including key generation, digital signatures and wrapping symmetric keys for transport
  • MAC and hash generation
  • Acceleration of handshake and frame encryption for SSL
  • PKCS #11 API

which has too many buzz words for me.

The manual Getting Started with z/OS Data Set Encryption is a very useful book.

My interpretation of what ICSF is:


  • Can create and store Public and Private certificates (as used in SSL and TLS). RACF can store its certificates in ICSF.
  • Can store symmetric keys used to encrypt data – such as data sets. Note: if you are using TLS the actual encryption of data over the network is done with a symmetric key.
  • Mange the hardware, tamper proof, keystores provided with z hardware. (You have to access the physical z machine to enter the master cryptographic keys).
  • To check credit card PIN number and other checks.
  • You can configure ICSF in a group of datasets, and switch to a different set.

ICSF facilities

ICSF has

  • A callable services API to allow you to call ICSF services from a program. There is a header file /usr/include/csfbext.h and SYS1.SIEAHDR.H which defines the function parameters.
  • Some ISPF panels to help you mange the ICSF entities.
  • Some batch command interfaces.

ICSF is not very usable

I found that ICSF was not very usable. For example

  • The ISPF panels are not intuitive. You can update the ICSF datasets in batch. You then have to refresh the in-memory copy.
    • For example, to refresh the CKDS data set and list it, using the ISPF panels for ICSF
      • 2 KDS MANAGEMENT -> 1 CKDS MANAGEMENT -> 1 CKDS OPERATIONS -> 2 REFRESH – Activate an updated CKDS.
      • Then PF3, 3 times.
    • To list the contents
      • 5 UTILITY -> 5 CKDS KEYS -> 1 List and manage all records
    • I would have had a page for KDS, and had a refresh option, and a list option on the same page.
  • I expected to be able to use ICSF using commands. It looks like I have to write programs to use the API! Some REXX programs are available for a subset of the function.
  • There is a lack of consistency. Two utilities doing similar things one has PARM=’REFESH,name’ the other has PARM=’name,REFRESH’. The utility for PKDS is CSFPUTIL. The utility for CKDS is CSFEUTIL.

It feels like ICSF has not yet been finished, more of an “Here are some API’s – good luck as you are on your own”, than a guide for the new user.

I’m writing some C programs to do some basic definitions, and pass parameters. I should not need to do this.

ICSF concepts

There are asymmetric keys such as private key and its public key. If you encrypt some text with a public key you need the private key to decrypt it. If you encrypt with the private key – you need the public key to decrypt it.

There are symmetric keys where the same key is used at each end. For example encrypt: change A to s, B to !; decrypt change s to A, ! to B.

Asymmetric keys are usually used in negotiating or sending a symmetric key to the remote end.

Symmetric keys are usually used to encrypt the payload. It is good practice to change the symmetric key periodically to make it harder for someone to break the cipher.

ICSF has

  • PKDS (Public Key Data Set) for storing Private and Public Asymmetric keys.
  • CKDS (Cryptographic Key Data Set) which is used to store Symmetric keys
  • TKDS (Token Key Data Set). When you are using keys stored in the hardware cryptographic facility, you have a token to reference the data.

The data in these key data sets, may be encrypted, for example by the hardware cryptographic facility. You can configure ICSF so your keys are encrypted, and in normal operation they are not available in clear text, as they are encrypted by the tamper proof hardware, and are used within the hardware, where they are decrypted and used.

Keys can be in one of several state

  • Active. The key can be used to process data. It is within its start and end dates (if present)
  • Archive. The key cannot be used to process data. For example you have backed up an encrypted data set to tape. If you delete the key, the data cannot be processed. If they key is archived then it cannot be used. If you need to access the backed up dataset, you can change the status to Active for the duration of the work.
  • Inactive – A key which has not been archived, and is outside of the start and end dates (if present).
  • Pre-active – I cannot find what this is. It is mentioned in the ISPF panels.


You can configure which ICSF data sets are current using, and other parameters via SYS1.PARMLIB(CSFPRMxx).

When you start the CSF procedure you specify the xx. For example in SYS1.PROCLIB concatenation member CSF,



You can use the SETICSF operator command to change some parameters for the duration of the CSF task.

You can use D ICSF, for example d ICSF,kds to give

No TKDS was provided.

To change use a different CSFPRMxx, you have to stop and restart CSF, specifying the CSFPRM suffix.

You need to plan your ICSF usage

You can set up data set encryption so when you create a data set, the data is automatically encrypted. You define a key and give it a label. If you delete the key, the data cannot be read. To be able to process the dataset you need RACF access to the dataset, and RACF access to the key.

The label is associated with the data set (so it you send the dataset to a remote system, it will still have the same label).

Most organisations say you much change your password periodically, typically every month. For similar reasons organisations say you should define a new key and use it, typically every month. This is called Key Rotation, where you roll over your key to a new value.

I could have a key with label ColinDSKey, and encrypt my data sets with it. I encrypt data set COLIN.AUG2021.LOG with this key. Next month if I create a new key and reuse the same label, I can encrypt the data set COLIN.SEPT2021.LOG and use the new key. However I will be unable to read COLIN.AUG2021.LOG, because ColinDSKey now has a new value.

I’ve seen presentations which say ” just re-encrypt all your datasets with the new key”. This sounds like a lot of work and a major disruption.

Another approach is to change the key label, for example ColinAug2021DSKey. When I generate a new key, it has a label ColinSept2021DSKey. I configure datasets to use the new label. Datasets with the old label can still be used, as long as the key exists. You can tell ICSF to archive the label (and key), so it cannot be used. If it is needed you make the key active, use the data set, and re archive the key.

To set the label for a data set, you can

  • Specify it in JCL. So you may have to change your JCL every month, or use a symbolic such as the month and year.

LU *

Use SMS and have rules to generate the label depending on your profile and the name of the data set.

Define a RACF profile for example ADDSD ‘PROTECT.*’ UACC(NONE) DFP(DATAKEY(AES2)) says for all datasets with a HLQ of PROTECT, then use key AES2.

When a dataset is allocated you get a message


You also need to think about encrypting your databases, which is another jump in complexity. As an old text book said “We’ll leave this as an exercise for the reader”.

To make the planning just a little! more complex; If you send an encrypted data set to another z/OS system, it will have the same label as when it was originally created, so you need the keys sent (securely) to the remote system for the data set to be processed, and coordinate naming conventions.

As the section header says You need to plan your ICSF usage. ICSF and data set encryption needs a lot of planning.