How do I get my client talking to the server with a signed certificate

Signed certificates are very common, but I was asked how I connected my laptop to my server, in the scenario “one up” from a trivial example.

Basic concepts

  • A private/public key pair are generated on a machine. The private stays on the machine (securely). The public key can be sent anywhere.
  • A certificate has ( amongst other stuff)
    • Your name
    • Address
    • Public key
    • Validity dates

Getting a signed certificate

When you create a certificate: it does a checksum of the contents of the certificate, encrypts the checksum with your private key, and attaches this encrypted value to the certificate.

Conceptually, you go to your favourite Certificate Authority (UKCA) building and they Sign it

  • They check your passport and gas bill with the details of your certificate.
  • They attach the UKCA public key to your certificate.
  • They do a checksum of the combined documents.
  • They encrypt the checksum with the the UKCA private key, and stick this on the combined document.

You now have a signed certificate, which you can send it to anyone who cares.

Using it

When I receive it, and use it

  • my system compares my copy of the UKCA public certificate with the one in your certificate – it matches!
  • Using (either) UKCA public certificate – decrypt the encrypted checksum
  • Do the same checksum calculation – and the two values should match.
  • If they match I know I can trust the information in the certificate.

This means the checking of the certificate requires the CA certificate that signed it.

To use a (Linux) certificate on z/OS you either need to

  • issue the RACF GENCERT command on the Linux .csr file, export it, then download it to Linux. The certificate will contain the z/OS CA’s certificate.
  • import the Linux CA certificate into RACF (This is the easy, do once solution.)

then

  • connect the CA certificate to your keyring, and usually restart your server.

Setting up my system

If the CA certificate is not on your system, you need to import it from a dataset.

You can use FTP, or use cut and paste to the dataset.

Once you have the CA certificate in your RACF database you can connect it to your keyring.

Create my Linux CA and copy it to z/OS

CA="docca256"
casubj=" -subj /C=GB/O=DOC/OU=CA/CN=LINUXDOCCA2564"
days="-days 1095"
rm $CA.pem $CA.key.pem

openssl ecparam -name prime256v1 -genkey -noout -out $CA.key.pem

openssl req -x509 -sha384 -config caca.config -key $CA.key.pem -keyform pem -nodes $casubj -out $CA.pem -outform PEM $days

openssl x509 -in $CA.pem -text -noout|less

Where my caca.config has

####################################################################
[ req ]
distinguished_name = ca_distinguished_name
x509_extensions = ca_extensions
prompt = no

authorityKeyIdentifier = keyid:always,issuer:always

[ca_distinguished_name ]
[ ca_extensions ]

subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always
basicConstraints = critical,CA:TRUE, pathlen:0
keyUsage = keyCertSign, digitalSignature,cRLSign

Running the command gave

Certificate:
Data:
...
Issuer: C = GB, O = DOC, OU = CA, CN = LINUXDOCCA256
...
Subject: C = GB, O = DOC, OU = CA, CN = LINUXDOCCA256
...
X509v3 extensions:
...
X509v3 Basic Constraints: critical
CA:TRUE, pathlen:0
X509v3 Key Usage:
Digital Signature, Certificate Sign, CRL Sign
...

Where it has CA:TRUE and X509v3 Key Usage:Certificate Sign

Which allows this to be used to sign certificates.

Installing the CA certificate on z/OS

You need to copy the docca256.pem file from Linux to a z/OS dataset (Fixed block, lrecl 80, blksize 80) you can use FTP or cut and paste. I used dataset COLIN.DOCCA256.PEM.

Import it into z/OS, and connect it to the START1.MYRING keyring as a CERTAUTH.

//COLRACF  JOB 1,MSGCLASS=H 
//S1 EXEC PGM=IKJEFT01,REGION=0M
//SYSPRINT DD SYSOUT=*
//SYSTSPRT DD SYSOUT=*
//SYSTSIN DD *
RACDCERT CHECKCERT('COLIN.DOCCA256.PEM')

*RACDCERT DELETE (LABEL('LINUXDOCA256')) CERTAUTH
RACDCERT ADD('COLIN.DOCCA256.PEM') -
CERTAUTH WITHLABEL('LINUXDOCA256') TRUST

RACDCERT CONNECT(CERTAUTH LABEL('LINUXDOCA256') -
RING(MYRING) USAGE(CERTAUTH)) ID(START1)

SETROPTS RACLIST(DIGTCERT,DIGTRING ) refresh
/*

Once you have connected the CA to the keyring, you need to get the server to reread the keyring, or restart the server.

Getting my Linux certificate signed by z/OS

This works, but is a bit tedious for a large number of certificates.

I created a certificate request file using

timeout="--connect-timeout 10"
enddate="-enddate 20290130164600Z"

ext="-extensions end_user"

name="docec384Pass2"
key="$name.key.pem"
cert="$name.pem"
p12="$name.p12"
subj="-subj /C=GB/O=Doc3/CN="$name
rm $name.key.pem
rm $name.csr
rm $name.pem
passin="-passin file:password.file"
passout="-passout file:password.file"
md="-md sha384"
policy="-policy signing_policy"
caconfig="-config ca2.config"
caextensions="-extensions clientServer"


openssl ecparam -name secp384r1 -genkey -noout -out $name.key.pem
openssl req -config openssl.config -new -key $key -out $name.csr -outform PEM -$subj $passin $passout

The certificate request file docec384Pass2.csr looks like

-----BEGIN CERTIFICATE REQUEST----- 
MIIBpzCCAS0CAQAwNDELMAkGA1UEBhMCR0IxDTALBgNVBAoMBERvYzMxFjAUBgNV
...
Tmmvu/nqe0wTc/jJuC4c/QJt+BQ1SYMxz9LiYjBXZuOZkpDdUieZDbbEew==
-----END CERTIFICATE REQUEST-----

With words CERTIFICATE REQUEST in the header and trailer records.

Create a dataset(COLIN.DOCLCERT.CSR) with the contents. It needs to be a sequential FB, LRECL 80 dataset.

  • Delete the old one
  • Generate the certificate using the information in the .csr. Sign it with the z/OS CA certificate
  • Export it to a dataset.
//IBMRACF2 JOB 1,MSGCLASS=H 
//S1 EXEC PGM=IKJEFT01,REGION=0M
//SYSPRINT DD SYSOUT=*
//SYSTSPRT DD SYSOUT=*
//SYSTSIN DD *

RACDCERT ID(COLIN ) DELETE(LABEL('LINUXCERT'))

RACDCERT ID(COLIN) GENCERT('COLIN.DOCLCERT.CSR') -
SIGNWITH (CERTAUTH LABEL('DOCZOSCA')) -
WITHLABEL('LINUXCERT')

RACDCERT ID(COLIN) LIST(label('LINUXCERT'))
RACDCERT EXPORT(label('LINUXCERT')) -
id(COLIN) -
format(CERTB64 ) -
password('password') -
DSN('COLIN.DOCLCERT.PEM' )

SETROPTS RACLIST(DIGTCERT,DIGTRING ) refresh

Then you can download COLIN.DOCLCERT.PEM to a file on Linux and use it. I used cut and paste to create a file docec384Pass2.zpem

I used it like

set -x 
name="colinpaice"
name="colinpaice"
name="docec384Pass2"
insecure=" "
insecure="--insecure"
timeout="--connect-timeout 100"
url="https://10.1.1.2:10443"
trace="--trace curl.trace.txt"

cert="--cert ./$name.zpem:password"
key="--key $name.key.pem"

curl -v $cert $key $url --verbose $timeout $insecure --tlsv1.2 $trace

Using wireshark I can see CA certificates being send from z/OS, and the docec384Pass2.lpem used; signed by a z/OS CA certificate.

Using the certificate in the Chrome browser.

  • In Chrome settings, search for cert.
  • Click security
  • Scroll down to Manage certificates, and select it
  • Select customised
  • Select import, and then select the file.
    • When I generated the file with the Linux CA it had a file type of .pem
    • When I signed it on z/OS, then downloaded it with a type of.zpem, I had to select all files (because the defaults are *.pem,*.csr,*.der..)

Why did my certificate mapping go wrong?

I had a working mapping for a Linux generated certificate to a z/OS userid. And then it wasn’t working. It took me 2 days before I had enlightenment. Although I had undone all of the changes I had made – well all but one.

I had defined

//IBMRACF  JOB 1,MSGCLASS=H 
//S1 EXEC PGM=IKJEFT01,REGION=0M
//SYSPRINT DD SYSOUT=*
//SYSTSPRT DD SYSOUT=*
//SYSTSIN DD *
RACDCERT DELMAP(LABEL('colinpaice'))ID(IBMUSER)
RACDCERT MAP ID(IBMUSER) -
WITHLABEL('colinpaice') -
SDNFILTER('CN=colinpaice.O=cpwebuser.C=GB')
SETROPTS RACLIST(DIGTNMAP, DIGTCRIT) REFRESH
racdcert listMAP id(IBMUSER)
/*

Which says it the certificate with Subject: C = GB, O = cpwebuser, CN = colinpaice come in, then it maps to IBMUSER. Yes, the terms are in a different order, and there are “.” instead of “.” but it worked.

I started working with JSON Web Tokens (JWT), and it stopped working. The userid was coming out as IZUSVR – which is the userid of z/OSMF. I struggled with traces, and wrote my own little program to map the certificate to a userid – but still it was IZUSVR.

The enlightenment.

With JWT they are signed by a private key, and the public key is used to check the signature (that is check the checksum of the data is valid). To do this, the keyring needs the certificate in the keyring.
I was lazy and used the same certificate to sign the JWT, as I used to do certificate logon to z/OSMF.

To put the certificate in the keyring you need to import the certificate. I copied the certificate from Linux, using cut and paste and imported it

I used

//IBMRACF2 JOB 1,MSGCLASS=H 
//S1 EXEC PGM=IKJEFT01,REGION=0M
//SYSPRINT DD SYSOUT=*
//SYSTSPRT DD SYSOUT=*
//SYSTSIN DD *
RACDCERT CHECKCERT('COLIN.COLIN.PAICE.PEM')
RACDCERT DELETE (LABEL('COLINPAICE')) ID(IZUSVR)
RACDCERT ADD('COLIN.COLIN.PAICE.PEM') -
ID(IZUSVR) WITHLABEL('COLINPAICE') TRUST


RACDCERT ID(IZUSVR) CONNECT(RING(CCPKeyring.IZUDFLT) -
USAGE(CERTAUTH) -
LABEL('COLINPAICE') -
id(IZUSVR))

SETROPTS RACLIST(DIGTCERT,DIGTRING ) refresh
/*

This imports the certificate and associates it with the specified userid, ID(IZUSVR).
Now, when the certificate arrives as part of the certificate logon to z/OSMF, it checks to see if it is in the RACF data base – yes it is – under userid IZUSVR. It does not use the RACDCERT MAP option.

I reran this job with userid ADCDB – and the JWT had ADCDB in the definition.

To make it more complex, the Liberty Web Server within z/OSMF caches some information, and this complicated the diagnosis. In the evening it worked – next morning after IPL – it didn’t!

Lesson learned

Use one certificate for certificate logon, and another certificate for JWT.

Mapping a certificate to a userid and so avoid needing a password is good – but…

You can use the RACDCERT MAP command to map a certificate to a userid, and so avoid the need for specifying a password. Under the covers code uses the pthread_security_np and pass a certificate, or a userid and password, and if validated, the thread becomes that userid, just the same as if the userid was logged on.

Is this secure?

If you store a userid and password on your laptop, even though the data may be “protected” someone who has access to your machine may be able to copy the file and so impersonate you.

With a public certificate and private key, if someone can access your machine, they may be able to copy these files and so impersonate you.

You can get dongles which you plug into your laptop on which you can store protected data. In order to use the data, you need the physical device.

You need to protect the RACF command

Because the RACFCERT command has the power to be dangerous, you need to protect it.

You do not want someone to specify their certificate maps to a powerful userid, such as SYS1. The documentation says

To issue the RACDCERT MAP command, you must have the SPECIAL attribute or sufficient authority to the IRR.DIGTCERT.MAP resource in the FACILITY class for your intended purpose.

For a general user to create a mapping associated with their own user ID they need READ access to IRR.DIGTCERT.MAP.

For a general user to create a mapping associated with another user ID or MULTIID, they need need UPDATE access to IRR.DIGTCERT.MAP.

What’s the best way to set this up?

I think that as part of your process for setting up userids, the process should create the mapping for the certificate to a userid. This way you do not have people creating the mapping. If a mapping already exists, you cannot create another mapping.

You may want an automated process which checks the approval, and issues the commands, and so you do not have humans with the authority to issue the commands.

Of course you’ll have a break-glass all powerful userid in case of emergencies.

But….


Even though the password had expired, I could logon using the certificate. If I revoked the userid the logon failed.

I used certificate logon from z/OSMF and issued console commands. The starts a TSO address space, and z/OSMF passes the commands and responses to the tso address space.

Once a TSO address space has been started, there are no more checks to see if the userid is still valid.

If you want to inactivate the userid, you’ll need to revoke it, and then cancel all the TSO address spaces running on behalf of the userid. Walking someone off site is not good enough. There may be scripts which are automated, and will logon with no human intervention.
TSO address spaces may be configured to be cancelled if there is no activity. If the TSO address space is kept busy, (for example by sending it requests) it may never be forced off.

Zowe: Planning – certificates

A private key is used for encryption and should be kept private. If someone has access to the private key they can impersonate you.

A public key is the opposite of the private key. It is used for decrypting data encrypted with the private key. The public key can (and should) be generally available.

Certificates are used in TLS for authentication and encryption, and can be used for identification. They include a public key.

A Certificate Authority(CA) certificate is used to validate other certificates. It involves doing a checksum of a certificate, and encrypting it with the CA private key – a process known as signing the certificate

To validate a certificate, the recipient needs a copy of the CA which was used to sign the original certificate. It can the decrypt the encrypted checksum, and compare it with the certificates checksum.

If you create a Certificate Authority certificate you will need to distribute this to all machines that might communicate with your server(possibly thousands of machines), and installed into the keystore on those machines. This can be a big task. Most system have one site wide CA certificate which is distributed to all machines. You might have a second CA to limit access to a system. This CA is used to sign the server certificates.

Creating certificates

As part of creating a certificate you create the private/public keys. There are different algorithms for these keys. Some are stronger than others (it takes more time and CPU to break them) Keys with elliptic curve algorithms are generally stronger than using RSA techniques, and there other techniques resistant to Quantum Computing.

You have to use a server certificate with RSA and keysize 2048.

I found that authentication with JWT (Java Web Tokens) only worked with RSA keys and not Elliptic Curves. This is because of encryption with JWT.

Key stores

You should use keyrings rather than .pem files, as they are more secure. .pem files can be copied, and anyone with authority can copy them. You have to give explicit permission to be allowed to access a keyring. Certificate and the private keys within a keyring can be stored in cryptographic hardware, and the private keys are never exposed in clear text.

Many systems uses a keystore for storing the private key used by the server, and a trust store for the Certificate Authority keys needed to validate any client certificate sent to the server. This can, but is not recommended, be the same as the keystore.

The keystore will need the server key. You can specify which key should be used.

  • the Certificate Authority keys needed to validate the server key.
  • the server userid needs access to the keyring. If the private key belongs to the server’s userid, then the server’s userid needs read access to the keyring. If the private key belongs to a different userid, the server’s userid needs update access to the keyring. See here for more information.

The trust store needs all the CA certificates which may be needed to verify a client certificate.

The client machine will have one or more certificates. A copy of the CA used to create these needs to be installed in the trust store on the server.

I understand that if you add a certificate to the trust store, you need to restart Zowe for it to be picked up, so try to get a list of all the CAs you will need before you start.

Validating certificates

The trust store needs the certificates to validate any client certificates sent to the server. This will usually just be Certificate Authority certificates.

Zowe works with z/OSMF. They communicate with certificates. The z/OSMF trust store keyring needs the CA of the Zowe server certificate, and the Zowe trust store keyring needs the CA of the z/OSMF server key. If they are not set up properly you can get messages “LoadBalancer does not contain an instance for the service zaas”.

If you have a site wide CA, which is the same for both of the server keys, then you do not need to do any more work, as both trust store keyrings will already have the CA. If Zowe and z/OSMF have different CA certificates, the CA certificates need to be connected to the other keyrings.

Subject Alternative Name

The Subject Alternative Name within a certificate provides the IP addresses, or IP Names of the server. A client can check this address with the IP address of the session, and terminate the session if they do not match. This is considered best practice. This check can be disabled in Zowe by using verifyCertificates NOSTRICT in the zowe.yaml file.

RACF allows one name or address when the certificate is defined, for example ALTNAME(IP(127.0.0.1))

On my z/OS system the command TSO NETSTAT HOME gives three addresses 127.0.0.1 and 10.1.1.2 and 10.1.2.6.

You can configure your sysplex, so all systems in the sysplex have the same IP address, and traffic gets routed internally to the correct system. Without this, if you start a server on a different LPAR it will have a different IP address, and so the validation will fail.

On my system, the zOSMF certificate did not have an ALTNAME specified, and so failed the Zowe checks. I had to set the Zowe option verifyCertificates NOSTRICT for it to work, until I fixed the certificate.

If the z/OSMF certificate has an ALTNAME(IP…) specified, use the IP address value when you configure zOSMF for example

zOSMF: 
host: 127.0.0.1
port: 10443
applId: IZUDFLT

Mapping certificates

If you are using client certificate to authenticate rather than a userid and password, then you’ll need to map certificates to userids, for example with the RACDCERT MAP command. You can specify which CA the certificates were signed with, and fields from the subject Distinguished Name. The question of which is better: using userid and password, or client certificate to logon has no easy answer

  • It is easy for a hacker to get a password (lost handbag, yellow sticky stuck to the screen, a couple of pints down the pub) It is easy to change a password once is is compromised.
  • It is harder for a hacker to get a certificate – but it is harder to change and re-issue a certificate. You have to get the updated certificate down to the client’s machine. It could be stolen if a hacker has access to the machine.
  • Using Biometric data to logon is the ultimate limit in this area. Hackers could steal it – but there is no way of changing it if it is compromised!

Decisions

You need to decide

  • Are you going to have a CA just for Zowe? or reuse the site CA.
    • If you are going to have a Zowe specific CA – how are you going to distribute it to all the client machines.
    • You’ll need to ensure Zowe and z/OSMF have the other’s CA certificates in their trust store.
  • Are you going to use Subject Alternative Name ALTNAME(IP(10.1.1.2))
    • What value of verifyCertificates STRICT|NOSTRICT are you going to specify in the zowe.yaml file.
  • Are you going to authenticate using certificates. You will need to set up mapping from certificate to userid. RACDCERT MAP
  • If you will be using JWT, and so need an RSA key in the server certificate

Why can’t java use my key ring?

I had a problem with z/OSMF. I configured it to use an exiting keyring, but it consistently refused to use it. I had messages like

[WARNING ] CWPKI0809W: There is a failure loading the defaultKeyStore keystore. If an SSL configuration references the defaultKeyStore keystore, then the SSL configuration will fail to initialize.

This blog post covers how I debugged this situation.

What seemed strange was this only occurred when an Elliptic Curve certificate was being used – and not an RSA certificate.

Even more curiouser was the documentation mentioned access to the <ringOwner>.<ringName>.LST resource in the RDATALIB class. See here. I didn’t have this defined and yet RSA certificates would work! So curiouser and curiouser (or for the people who like correct grammar, curiouser and more curiouser).

All applications needing access to certificates and private keys use the R_datalib callable service.

The bottom line

  • z/OSMF has userid IZUSVR
  • I had a keyring and used two certificates
    • An RSA certificate, CCPKeyring.IZUDFLT, belonging to userid IZUSVR – based on the sample JCL provided by z/OSMF
    • An existing Elliptic Curve certificate NISTEC224 belonging to userid COLIN. This works else where.
  • Without <ringOwner>.<ringName>.LST defined the class(RDATALIB) the RSA certificate worked
  • Without <ringOwner>.<ringName>.LST defined the class(RDATALIB) the Elliptic Curve certificate failed
  • Once I found the problem I defined <ringOwner>.<ringName>.LST in class(RDATALIB), and gave the userid IZUSVR Update access to it – and the Elliptic curve worked
  • The reasons (being wise after the event)
    • R_datalib checks access on one profile in the RDATALIB class first – <ringowner>.<ringname>.LST. If there is none, it will fall back to check on two profiles in the FACILITY class – IRR.DIGTCERT.LISTRING and IRR.DIGTCERT.GENCERT. If the certificate is not owned by the accessing ID (except CERTAUTH or SITE), RDATALIB class has to be used for private key access.
    • This is true for the RSA certificate, used the IRRDIGTCERT.LISTRING class(FACILITY) and had access. So this worked.
    • For the Elliptic Curve, the caller’s userid (IZUSVR) is not the associated with the certificate (COLIN) so this fails, and the logic drops through to the RDATALIB checking.
    • The caller’s user ID has READ or UPDATE authority to the ..LST resource in the RDATALIB class. READ access enables retrieving one’s own private key, UPDATE access enables retrieving other’s. The ring did not exist, and so this access was not given.

How did I debug this? – Using Java trace

Adding configuration to z/OSMF

I copied /global/zosmf/configuration/local_override.cfg to /global/zosmf/configuration/local_override.colin

I edited/global/zosmf/configuration/local_override.cfg and changes the JVM options line to

JVM_OPTIONS=”-Xoptionsfile=’/global/zosmf/configuration/local_override.colin'”

I edited the local_override.colin, deleted all but the JVM options line, then split the line at \n so it looks like

-Dcom.ibm.ws.classloading.tcclLockWaitTimeMillis=300000
-Xscmx150M
-Xquickstart

Add debug information to the configuraton file

I added

-Djava.security.auth.debug=pkcs11keystore
-Dlog.level=Error

The output

[err] Jan 17, 2025 8:18:52 AM com.ibm.crypto.ibmjcehybrid.provider.HybridRACFKeyStore engineLoad 
TRACE: Loading keyring CCPKeyring.IZUDFLT as a JCECCARACFKS type keystore.
...
[err] Jan 17, 2025 8:19:02 AM com.ibm.crypto.hdwrCCA.provider.RACFInputStream getEntry
FINER: The private key of NISTEC224 is not available or no authority to access the private key
[err] Jan 17, 2025 8:19:02 AM com.ibm.crypto.ibmjcehybrid.provider.HybridRACFKeyStore engineLoad
TRACE: Error loading and storing certificates and key material from underlying JCECCARACFKS keyring CCPKeyring.IZUDFLT
java.io.IOException: The private key of NISTEC224 is not available or no authority to access the private key . This can be expected if the IBMJCECCA is not setup correctly or
ICSF is down. Will now attempt to load the keyring as a JCERACFKS keyring.

Which is not a very helpful message.

How did I debug this? – Using RACF trace

R_datalib is the callable service to ALL the exploiters which need access to a RACF keyring (certificates and private keys). It is r_datalib or its alias irrsdl00 with callable type number 41.

Enable the RACF trace

#SET TRACE(CALLABLE(TYPE(41))JOBNAME(IZU*))

Start GTF

S GTF.GTF,M=GTFRACF

This reported

IEF403I GTF - STARTED - TIME=08.17.03                                  
IEF188I PROBLEM PROGRAM ATTRIBUTES ASSIGNED
AHL121I TRACE OPTION INPUT INDICATED FROM MEMBER GTFRACF OF PDS
USER.Z24C.PROCLIB
TRACE=USRP
USR=(F44)
END
AHL103I TRACE OPTIONS SELECTED --USR=(F44)
AHL906I THE OUTPUT BLOCK SIZE OF 27998 WILL BE USED FOR OUTPUT 702
DATA SETS:
SYS1.TRACE

I started z/OSMF until it failed.

Stop GTF

p GTF 
AHL006I GTF ACKNOWLEDGES STOP COMMAND
AHL904I THE FOLLOWING TRACE DATASETS CONTAIN TRACE DATA :
SYS1.TRACE

Use IPCS to look at the dump, using command GTF USR(ALL). Go to the bottom of the output, use the command report view. This gives an ISPF edit session.

  • x all
  • f ‘RACF Reason code:’ all
    • You are interested in the non zero codes. “Label” each line of interest using the line prefix command .a, .b etc.
  • reset
  • loc .a
    • This will position you by the labelled line. Look up the RACF return and reason codes here. I had Reason Code 2c, which is decimal 44. Look for the keyring, or other information. I do not know which data tells you which sub operation r_datalib was doing, but for me it had the keyring name “CCPKeyring.IZUDFLT “. The description in the reason code documentation does not cover the situation of not having update access to the keyring, so I’ve raised a doc comment on it.

Certificate dates with ICSF and PKISERV

Digging into certificates provided by ICSF, I got confused with the dates.

There are 3 places that start/end dates can be, and they have different meanings and uses.

  1. The validity period you see in the certificate is part of the certificate itself. That is added at certificate creation and enforced by the application (such as System SSL).
  2. Within ICSF there are fields START DATE/END DATE you see in the panels are CKA_START_DATE and CKA_END_DATE. They are defined in the PKCS#11 standards but are not enforced.
  3. Within record metadata for a KDSR format record, you will see Cryptoperiod start date/Cryptoperiod end date. This is enforced by ICSF. Usage outside this time frame is not permitted.

Note that PKCS#11 services are the only place you can see all three of these. Neither CKDS nor PKDS can hold certificates, nor do they support PKCS#11 attributes.

Official document

The standards document PKCS #11 Cryptographic Token Interface Base Specification says

CKA_START_DATE – Start date for the certificate (default empty)
CKA_END_DATE – End date for the certificate (default empty

Section 4.6.2 (Certificate objects Overview):
The CKA_START_DATE and CKA_END_DATE attributes are for reference only; Cryptoki does not attach any special meaning to them. When present, the application is responsible to set them to values that match the certificate’s encoded “not before” and “not after” fields (if any).

Section 4.7.2 (Key Objects Overview) has similar wording:
Note that the CKA_START_DATE and CKA_END_DATE attributes are for reference only; Cryptoki does not attach any special meaning to them. In particular, it does not restrict usage of a key

Thanks to Eric Rossman, for helping me understand this.

Setting up Linux to z/OS certificates

Several times I have had to set up certificates between Linux and z/OS and struggled for a day to get them working. Once you are familiar with doing it – it is easy. As the last time I needed to do this was over a year ago, I’ve forgotten some of the details. This blog post is to help me remember what I need to do, and to help other who struggle with this.

I’m ignoring self signed.

Basic TLS

A certificate contains

  • who it belongs to, such as CN=COLIN,O=SSS
  • the date range the certificate is valid
  • a public key
  • meta data about the key: What algorithm does the public key use, what parameters were used in the key generation, for example, algorithm=RSA, Keysize=2048.

There is a private key.

  • If you encrypt using the private key, you can use the public key to decrypt it.
  • If you encrypt using the public key, you can use the private key to decrypt it.
  • If you encrypt something with my public key, and then encrypt it with your private key. I know it came from you (or someone with your private key) and only I (or someone with my private key) can decrypt it.

Anyone can have the public key. You keep the private key secure.

Certificate Authority. This is used in validating the trust of certificates. You send your certificate to the CA, The CA does a checksum of your data, and encrypts this checksum with the CA private key. It returns your original data appended with the encrypted checksum, and information about the CA, and what was used to calculate the checksum. If someone else has the CA public key, they can do the opposite process. Do the checksum calculation, and decrypt the checksum value in the certificate, using the CA public key. If they match you know it was signed by the CA. This is known as signing the certificate.

To be able to validate a certificate sent to it, the client end needs the CA of the server end. The server needs the CA of the client end to be able to validate the client’s certificate.

During the handshake to establish the TLS connection there is a flow like

  • Establish the cipher spec to use
  • Server sends down its certificate, the client checks it
  • Servers sends down “Certificate request”, and these are the certificate(CAs) I know about
  • The client goes through it’s list of certificates (usually only one), to find the first certificate with a CA in the list sent from the server.
  • sends the client certificate to the server
    • The server checks the certificate. For example the server may be set up to accept a subset of valid algorithms, for example TLS 1.2, and Elliptic Curve. If a certificate is sent up using RSA, then this is not accepted
    • The server checks the signature of the certificate, finds the CA name, checks in the trust store for this CA, and validates the signature. Depending on the application it may check all the CA’s in the CA chain.

What do you need for the handshake to work

  • You need to have a Certificate Authority to sign certificates. In the CA certificate are some flags that say this is a CA.
  • You need to send the public key of each CA to the other end. You normally need to do this just once, and keep using the same certificates for all your TLS work.
  • You need to have a key store/trust store/keyring to hold certificates.
  • On z/OS
    • you may have a keyring for different projects, for example MQ, and TN3270.
    • You need to connect the client CA into each keyring where it will be used.
  • You need to check that the certificates are compatible with the remote end, such as Algorithm etc.

Openssl files

When using openssl, you can store common information in a configuration file. See here. This configuration file has some required options, and some optional options where you can specify common options you frequently use.

If you are using the openssl req command (for example), by default it will look for a section called [req]. This can in turn point to other sections. Using this file you can specify most of your fields in one place, and just override the specific ones.

Create a CA certificate on Linux

I have a bash file docca.sh file on Linux.

CA=”docca256″
casubj=” -subj /C=GB/O=DOC/OU=CA/CN=SSCA256″
days=”-days 1095″
rm $CA.pem $CA.key.pem

openssl ecparam -name prime256v1 -genkey -noout -out $CA.key.pem1

openssl req -x509 -sha384 -config caca.config -key $CA.key.pem2 -keyform pem -nodes $casubj -out $CA.pem3 -outform PEM $days

openssl x509 -in $CA.pem -text -noout|less4

This

  1. creates a private key (docca256.key.pem)
  2. self signs it. For any parameters not specified, it uses the configuration file caca.config and section “req” (signing request) within it.
  3. produces a public certificate in docca256.pem. This file will need to be sent to the backend servers. You can use cut and paste or FTP as ASCII.
  4. displays the x509 data

The caca.config file has

[ req ]
distinguished_name = ca_distinguished_name
x509_extensions = ca_extensions

prompt = no

authorityKeyIdentifier = keyid:always,issuer:always

[ca_distinguished_name ]
# C=GB
# O=DOC
# OU=Stromness
# CN=SSSCA4

####################################
[ ca_extensions ]

subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always
basicConstraints = critical,CA:TRUE, pathlen:0
keyUsage = keyCertSign, digitalSignature,cRLSign

The distinguished_name = ca_distinguished_name says go and look in the file for a section [ca_distinguished_name], and x509_extensions = ca_extensions says go and look for a section called [ca_extensions]. You can specify your own names, for example I could have used section1, and s2.

When prompt = yes, openssl takes as defaults the values in the distinguished_name section. When prompt = no, the distinguished_name is still required – but the contents of the section are ignored.

The values in the x509_extensions are defined here.

Creating an Elliptic Curve certificate on Linux

I used another bash script docecadad.sh, to document an ElliptiCal certificate for userid ADCD. It uses the CA defined above.

name="docecadcd"
key="$name.key.pem"
cert="$name.pem"
subj="-subj /C=GB/O=Doc/CN="$name
CA="docca256"
cafiles="-cert $CA.pem -keyfile $CA.key.pem "

enddate="-enddate 20240130164600Z"
passin="-passin file:password.file"
passout="-passout file:password.file"

rm $name.key.pem
rm $name.csr
rm $name.pem

#define a certificate with elliptic key with size 256

openssl ecparam -name prime256v1 -genkey -noout -out $name.key.pem 
#create a certificate request (ie hello CA please sign this)
openssl req -config openssl.config -new -key $key -out $name.csr -outform PEM -$subj $passin $passout

# sign it.

caconfig="-config ca2.config"
policy="-policy signing_policy"
extensions="-extensions clientServer"

md="-md sha384"

openssl ca $caconfig $policy $md $cafiles -out $cert -in $name.csr $enddate $extensions

# display it 
openssl x509 -in $name.pem -text -noout|less

Where the openssl.config file has

[ req ]
default_bits       = 2048

distinguished_name = server_distinguished_name
req_extensions     = server_req_extensions
string_mask        = utf8only
subjectKeyIdentifier   = hash
#extendedKeyUsage     = critical, codeSigning


[ server_req_extensions ]

subjectKeyIdentifier = hash
# subjectAltName       = DNS:localhost, IP:127.0.0.1, IP:127.0.0.6
# nsComment            = "OpenSSL"
keyUsage             = critical, nonRepudiation, digitalSignature
# extendedKeyUsage     = critical, OCSPSigning, codeSigning
subjectKeyIdentifier   = hash 

[ server_distinguished_name ]
#c=GB
#o=SSS
#cn=mqweb
  • See above for the distinguished_name value.
  • req_extensions says use the section [server_req_extensions]

The ca2.config file used to sign it has

HOME            = .
RANDFILE        = $ENV::HOME/.rnd

####################################################################
[ ca ]
default_ca    = CA_default      # The default ca section
####################################################################
[ CA_default ]
default_days     = 1000         # How long to certify for
default_crl_days = 30           # How long before next CRL
#default_md       = sha1       # Use public key default MD
default_md       = sha256       # Use public key default MD
preserve         = no           # Keep passed DN ordering

x509_extensions = ca_extensions # The extensions to add to the cert

email_in_dn     = no            # Don't concat the email in the DN
copy_extensions = copy          # Required to copy SANs from CSR to cert

#defaults
base_dir      = .
certificate   = $base_dir/cacert.pem   # The CA certifcate
private_key   = $base_dir/cakey.pem    # The CA private key
new_certs_dir = $base_dir              # Location for new certs after signing
database      = $base_dir/index.txt    # Database index file
serial        = $base_dir/serial.txt   # The current serial number

unique_subject = no  # Set to 'no' to allow creation of
                     # several certificates with same subject.


####################################################################
[ ca_extensions ]

subjectKeyIdentifier   = hash
authorityKeyIdentifier = keyid:always, issuer:always
basicConstraints       = critical,CA:TRUE, pathlen:0
keyUsage               = nonRepudiation

####################################################################

[ signing_policy ]
countryName            = optional
stateOrProvinceName    = optional
localityName           = optional
organizationName       = optional
organizationalUnitName = optional
commonName             = supplied

[ clientServer ]

keyUsage               = digitalSignature, keyAgreement, digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
subjectAltName         = DNS:localhost, IP:127.0.0.1, 
extendedKeyUsage       = serverAuth,clientAuth
subjectKeyIdentifier   = hash
authorityKeyIdentifier = keyid:always, issuer:always
nsComment  = "clientserver"

The policy (my [ signing_policy] ) must have entries in it to create a valid Subject Distinguished name. Without it, I got a strange RACF code (0x0be8044d).

Send the CA to z/OS and import it

You need to send the CA public certificate to z/OS. This file looks like

-----BEGIN CERTIFICATE-----                                      
MIIFbTCCA1WgAwIBAgIUJw+gLLSFxqCyTdIyEUWyQ/g9JnEwDQYJKoZIhvcNAQEL.
...
-----END CERTIFICATE----- 

You can FTP the file, or create the file and use cut and paste. The file needs to be a sequential dataset with format VB. My file is VB, lrecl=256,blksize=6233. For the FTP I used

put docca256.pem ‘colin.docca256.pem’

You need to import this into RACF, and connect it to the keyrings.

//IBMRACF  JOB 1,MSGCLASS=H                                     
//S1  EXEC PGM=IKJEFT01,REGION=0M                               
//SYSPRINT DD SYSOUT=*                                          
//SYSTSPRT DD SYSOUT=*                                          
//SYSTSIN DD *                                                  
RACDCERT CHECKCERT('COLIN.DOCCA256.PEM') 
/*                       

The CHECKCERT gave me

Certificate 1:                                                          
                                                                        
  Start Date: 2022/10/09 11:45:43                                       
  End Date:   2025/10/08 11:45:43                                       
  Serial Number:                                                        
       >782A62948699FF3FB00238FB296E4A647B7DF07C<                       
  Issuer's Name:                                                        
       >CN=SSCA256.OU=CA.O=DOC.C=GB<                                    
  Subject's Name:                                                       
       >CN=SSCA256.OU=CA.O=DOC.C=GB<                                    
  Signing Algorithm: sha384ECDSA                                        
  Key Usage: HANDSHAKE, CERTSIGN                                        
  Key Type: NIST ECC                                                    
  Key Size: 256                                                         
                                                                        

Which matches what I expected, and gave me information about the certificate – ECC, 256, and signed with SHA 384 ECDSA, (from the -sha384 parameter above).

Define it to RACF and connect it to the user’s keyring

racdcert list  (label('Linux-CA256')) CERTAUTh 
RACDCERT DELETE  (LABEL('LINUXDOCCA256'))    CERTAUTH             
              
RACDCERT ADD('COLIN.DOCCA256.PEM') -                            
          CERTAUTH  WITHLABEL('LINUXDOCA256') TRUST 

RACDCERT ID(START1) CONNECT(RING(MQRING)-        
                            CERTAUTH     -       
                            LABEL('LINUXDOCCA256'))                     

If you delete a certificate, then it is removed from all keyrings. Once you have re-added it you need to reconnect it to all the keyrings. If you list the label (racdcert list (label(‘Linux-CA256’)) certauth) it will display where it is used, so you can read it.

Download the z/OS CA certificate

I downloaded the z/OS exported certificate in .pem format. it looks like

-----BEGIN CERTIFICATE-----                                       
MIIDYDCCAkigAwIBAgIBADANBgkqhkiG9w0BAQsFADAwMQ4wDAYDVQQKEwVDT0xJ  
... 
+9TRng==                                                          
-----END CERTIFICATE-----

You can use ftp or cut and paste. I created doczosca.pem.

Use it!

Before I could use it, I had to set up the server’s certificate, and download the z/OS CA certificate

I set up a bash script scl2.sh

name=docecadcd
host="-connect 10.1.1.2:4000"
CA="--CAfile doczosca.pem "

openssl s_client $host  $CA -cert $name.pem -certform PEM -key $name.key.pem -keyform PEM
 

Using certificates to logon to z/OS.

I was testing out certificate access to logon to z/OS using pthread_secure_applid() services . It took a little while to get my program working, but once it was working I tried to be “customer like” rather than a simple Unit Test. The documentation is not very clear, but it does work.

You can create a RACF definition for the simple case

  • For a certificate where the Subject Distinguished Name(DN) matches the definition’s Subject DN, then use userid xyz.
  • For a certificate where part of the Subject DN matches the definitions Subject DN, then use userid ijklm.

These both default to using an APPLID OMVSAPPL

I wanted to say

  • for application id ZZZ, if a certificate with this subject DN, then use userid TESTZ
  • for application id YYY if a certificate with the same subject DN, then use userid TESTY

Topics covered n this post:

How to set up your enterprise certificates

If you want to control certificate to userid mapping, at an individual level

You can use the following, where SDN is the Subject Distinguished Name from the certificate,

RACDCERT MAP ID(....  ) SDN(...)

for each individual.

To remove access you just delete the profile (and refresh RACLIST).

You can also specify the Issuers Distinguished Name (IDN) so you refer to the correct certificate.

If you want to control certificate to userid mapping, at the group level

You can use a Subject DN filter. This may mean you need to define your Subject DN with Organisation Units(OU), as

  • CN=COLIN,OU=TEST,O=MYORG
  • CN=MARY,OU=SALES,O=MYORG

You can then have a filter SDN(‘OU=TEST,O=MYORG’) to allow just those in the OU=TEST group to logon, and sales people will not get access.

If you then want to prevent individuals from getting access you need to define a specific profile, and point it to a userid which can do nothing.

You could also have your certificates issued by different CA’s For example, have a certificate with an Issuer Distinguished Name(IDN) including the department name.

  • Subject DN(CN=COLIN,OU=TEST,O=MYORG) Issuer DN(OU=TEST,OU=CA,O=MYORG)

and specify IDN(OU=TEST,OU=CA,O=MYORG).

Note: with this, if someone changes department, and moved from Sales to Test, they will need a new certificate.

Some people may require more than one certificate. For example someone who has normal access for their day to day job, and super powers for emergencies.

Note: In addition to getting access with a certificate you may still want to use a password.

Define a certificate to user mapping (simple case)

Use a fully qualified Subject DN filter

For example, a certificate has SDN CN=docec256.O=Doc.C=GB .

//COLRACF  JOB 1,MSGCLASS=H 
//S1  EXEC PGM=IKJEFT01,REGION=0M 
//STEPLIB  DD  DISP=SHR,DSN=SYS1.MIGLIB 
//SYSPRINT DD SYSOUT=* 
//SYSTSPRT DD SYSOUT=* 
//SYSTSIN DD * 

RACDCERT DELMAP(LABEL('CP'))  ID(COLIN) 
RACDCERT MAP ID(COLIN  )  - 
   SDNFILTER('CN=docec256.O=Doc.C=GB')                  - 
   IDNFILTER('CN=SSCA256.OU=CA.O=DOC.C=GB')             - 
   WITHLABEL('CP') 
RACDCERT LISTMAP ID(COLIN) 
SETROPTS RACLIST(DIGTNMAP, DIGTCRIT) REFRESH 
/* 

This uses both Subject Distinguished Name, and Issuer Distinguished Name. You can use either or both filters.

With this definition when I used openssl s_client to talk to my server application running on z/OS. When I specified the client certificate with the specified Subject DN and signer, I could use:

  • AT-TLS, use BPX1IOC() and retrieve the userid. Internally this uses applid=OMVSAPPL
  • do it myself
    • retrieve the certificate with the BPX1IOC() TTLS_QUERY_ONLY call;
    • use rc = pthread_security_applid_np( __CREATE_SECURITY_ENV,…. “OMVSAPPL”) passing the certificate and the applid OMVSAPPL

The code checks my the extracted userid (COLIN) has read access to the profile OMVSAPPL in class(APPL)) and, if it has access, it returns the userid to the application.

See below if you do not want to use applid OMVSAPPL

Use a partially qualified Subject DN filter

Instead of a fully qualified Subject DN, CN=docec256.O=Doc.C=GB. You can use a partially qualified DN, for example CN=docec256.O=Doc.C=GB. Any certificate which has a DN including O=Doc.C=GB will be accepted

RACDCERT DELMAP(LABEL('CPGEN'))  ID(ADCDF) 
RACDCERT MAP ID(ADCDF  )  - 
   SDNFILTER('O=Doc.C=GB')                  - 
   WITHLABEL('CPGEN') 
RACDCERT LISTMAP ID(ADCDF) 
SETROPTS RACLIST(DIGTNMAP, DIGTCRIT) REFRESH 

With this definition when I used openssl s_client to talk to my server application running on z/OS. When I specified the client certificate with the specified Issuer CN, it worked the same way as the simple case above.

The code checks my the user extracted userid (ADCDF) has read access to the profile OMVSAPPL in class(APPL)) and, if it has access, it returns the userid to the application.

Define a certificate with mutliid mapping

A specific Subject DN gets a different userid depending on the application id.

As above you can specify an Issuer Distinguished Name or a Subject Distinguished Name.

Use an Issuer Distinguished Name

Use an Issuer certificate, so any certificate issued by DN this will be covered.

I defined the profile for my Issuer CA certificate. The definition below says – any certificate issued by this CA.

RACDCERT DELMAP(LABEL('CPMULTI')) MULTIID 

RACDCERT MULTIID MAP WITHLABEL('CPMULTI') TRUST - 
  IDNFILTER('CN=SSCA256.OU=CA.O=DOC.C=GB')      - 
  CRITERIA(ZZAPPLID=&APPLID) 

Define which userid to use based on the CRITeria

RDEFINE DIGTCRIT ZZAPPLID=ZZZ  APPLDATA('ADCDZ') 
RDEFINE DIGTCRIT ZZAPPLID=AAA  APPLDATA('ADCDF') 

In my program I had

struct __certificate  ct; 
ct.__cert_type = __CERT_X509; 
char * pData = (char *)  ioc.TTLSi_BufferPtr; 
       
ct.__cert_length = ...
ct.__cert_ptr    = ...;
rc = pthread_security_applid_np(__CREATE_SECURITY_ENV,
         __CERTIFICATE_IDENTITY, 
         sizeof(ct), 
         &ct, 
         "", 
         0,
        "AAA"); 

With this, the CRITERIA(ZZAPPLID=&APPLID) becomes CRITERIA(ZZAPPLID=AAA), which maps to CRITeria

RDEFINE DIGTCRIT ZZAPPLID=AAA  APPLDATA('ADCDF'), 

and so maps to userid ADCDF.

When applid ZZZ was used instead of AAA, then

RDEFINE DIGTCRIT ZZAPPLID=AAA  APPLDATA('ADCDF')

AT-TLS only seems to be able to use the APPL OMVSAPPL (the default). I could not find a way of getting it to use an APPLID, so I had to use pthead_security_appl_np to be able to use an applid different from the default.

Use a subject DN

You can use an explicit Subject DN

 RACDCERT MULTIID MAP WITHLABEL('CPMULTIU') TRUST - 
     SDNFILTER('CN=docecgen.O=Doc2.C=GB')            - 
   CRITERIA(UAPPLID=&APPLID) 

 RDEFINE DIGTCRIT UAPPLID=AAA  APPLDATA('ADCDA') 
 RDEFINE DIGTCRIT UAPPLID=BBB  APPLDATA('ADCDB') 

the userid used depending which APPLID was specified in my application.

I could use a subset of the the SDN

RACDCERT DELMAP(LABEL('CPMULTIU')) MULTIID 
RDELETE DIGTCRIT APPLID=OMVSAPPL 
RDELETE DIGTCRIT APPLID=ZZZ 
                                                                   
RACDCERT MULTIID MAP WITHLABEL('CPMULTIU') TRUST - 
    SDNFILTER('O=Doc2.C=GB')            - 
  CRITERIA(UAPPLID=&APPLID) 

RDEFINE DIGTCRIT UAPPLID=AAA  APPLDATA('ADCDD') 
RDEFINE DIGTCRIT UAPPLID=BBB  APPLDATA('ADCDE') 

Creating definitions

What the documentation does not say, is that you can have any keyword in the criteria, as long as the substitute value has a DIGTCRIT.

This means you can have

RACDCERT MULTIID MAP ...    CRITERIA(ZORK=&APPLID) 

and have statements like

RDEFINE DIGTCRIT ZORK=AAA  APPLDATA('IBMUSER')

Controlling access to the applid

If there is a profile for the applid in CLASS(APPL) the userid will need read access to the profile.

If the profile is not defined, then anyone can use the profile.

Problem I experienced

ESRCH: errno 143 EDC5143I No such process. errno2 0be8044c

I got messages

ESRCH:The user ID provided as input is not defined to the security product or does not have an OMVS segment defined
pthread_s… rc = -1 errno 143 EDC5143I No such process. errno2 0be8044c

Where TSO BPXMTEXT 0be8044c gives

BPXPTSEC 01/05/18
JRNoCertforUser: There is no userid defined for this certificate. Action: Ensure the userid is known to the SAF service.

Cause 1:

I used an APPLID which did not have a criteria

I also got this when I used pthread_security_applid_np(…) with an an applid which did not have a matching RDEFINE DIGTCRIT

For example the following worked

  • applid AAA and RDEFINE DIGTCRIT UAPPLID=AAA APPLDATA(‘ADCDA’)

when I used a different applid I got the “EDC5143I No such process. errno2 0be8044c” message, along with the following on the joblog.

ICH408I USER(COLIN ) GROUP(SYS1 ) NAME(COLIN PAICE )
DIGITAL CERTIFICATE IS NOT DEFINED. CERTIFICATE SERIAL NUMBER(027C)
SUBJECT(CN=docecgen.O=Doc2.C=GB) ISSUER(CN=SSCA256.OU=CA.O=DOC.C=GB).

Cause 2:

In the definitions I had the wrong case: c=GB and c=gb.

Cause 3:

NOTRUST was specified

RACDCERT MULTIID MAP WITHLABEL('CPMULTIU') noTRUST -
SDNFILTER('CN=docecgen.O=Doc2.C=GB') -
CRITERIA(UAPPLID=&APPLID)

This also had a message on the job log:

ICH408I USER(START1 ) GROUP(SYS1 ) NAME(####################)
DIGITAL CERTIFICATE DEFINED TO A RESERVED USER ID. CERTIFICATE SERIAL
NUMBER(027C) SUBJECT(CN=docecgen.O=Doc2.C=GB) ISSUER(CN=SSCA256.OU=C
A.O=DOC.C=GB).

Cause 4:

I had specified the certificate’s DN in Issuers DN. It should have been SDNFILTER(‘CN=rsarsa.O=cpwebuser.C=GB’)

EMVSSAFEXTRERR 163 EDC5163I SAF/RACF extract error. errno2 0be8081c

pthread_secuity_applid_np() rc = -1 errno 163 EDC5163I SAF/RACF extract error. errno2 0be8081c

TSO BPXMTEXT 0be8081c , just gives

BPXPTSEC 01/05/18

with no message description

Cause 1:

I got this when I used

RACDCERT MULTIID MAP WITHLABEL('CPMULTIU') TRUST - 
    SDNFILTER('CN=docecgen.O=Doc2.C=GB')            - 
  CRITERIA(UAPPLID=&APPLID) 

and the SDNFILTER value was in upper case. When I corrected it (to the above) it worked.

It looks like certificate filter not found.

Cause 2:

I had a lower case keyword such as SDNFILTER(‘CN=docecgen.O=Doc2.c=GB’)

EMVSSAFEXTRERR 163 EDC5163I SAF/RACF extract error. errno2 0be80820

TSO BPXMTEXT 0be8082 gave

BPXPTSEC 01/05/18

and no other information.

I had

RACDCERT MULTIID MAP WITHLABEL('CPMULTIU') TRUST - 
    SDNFILTER('CN=docecgen.O=Doc2.C=GB')            - 
  CRITERIA(UAPPLID=&APPLID) 

RDEFINE DIGTCRIT UAPPLID=ZZZ  APPLDATA('ADCDB') 

and userid ADCDB had no access to the RACF resource class(APPL) ZZZ.

IBM reason code 0x0BE80820 is related to a SAF (System Authorization
Facility) authorization error encountered during a session switch,
This error indicates thatthe system believes the user lacks the necessary authorization to switch to the target user ID , even though the profile is intended to handle this authorization.

Local fix: Give users and group READ access to profile OMVSAPPL in
class APPL.

EMVSERR 157 EDC5157I An internal error has occurred. errno2 0be800fc.

TSO BPXMTEXT 0be800fc gave

BPXPTSEC 01/05/18
JRSAFNoUID: The user ID has no UID

Action: Create an OMVS segment with a UID.

Cause:

If I display the userid LU ADCDG OMVS it gave UID= NONE.

I had created this situation using ALU ADCDG OMVS(NOUID). I reset it back using tso ALU ADCDG OMVS(UID(990098)).

How to import a certificate from openssl into z/OS

This question came up in an email exchange after someone had upgraded openssl from 1.1.1 to v3.

There are two format certificates – text, and binary.

Text certificate

The text certificate looks like

Certificate:                                        
    Data:                                           
        Version: 3 (0x2)                            
        Serial Number: 633 (0x279)                  
        Signature Algorithm: ecdsa-with-SHA384      
...
-----BEGIN CERTIFICATE-----                                      
MIICgTCCAiegAwIBAgICAnkwCgYIKoZIzj0EAwMwOjELMAkGA1UEBhMCR0IxDDAK 
BgNVBAoMA0RPQzELMAkGA1UECwwCQ0ExEDAOBgNVBAMMB1NTQ0EyNTYwHhcNMjMw 
MzE5MTIzODA1WhcNMjQwMTMwMTY0NjAwWjAuMQswCQYDVQQGEwJHQjEMMAoGA1UE 
CgwDRG9jMREwDwYDVQQDDAhkb2NlYzI1NjBZMBMGByqGSM49AgEGCCqGSM49AwEH 
...
-----END CERTIFICATE-----    

This has both a text version, and a base 64 encoded version within it.

On z/OS create a dataset with this file. Then use JCL like

//S1  EXEC PGM=IKJEFT01,REGION=0M 
//SYSPRINT DD SYSOUT=* 
//SYSTSPRT DD SYSOUT=* 
//SYSTSIN DD * 
RACDCERT CHECKCERT('COLIN.DOCEC256.NEW.PEM')           

This checks the file is usable, and you can check the contents before you install it on your system.

It produced output like

Certificate 1:                                               
                                                             
  Start Date: 2023/03/19 12:38:05                            
  End Date:   2024/01/30 16:46:00                            
  Serial Number:                                             
       >0279<                                                
  Issuer's Name:                                             
       >CN=SSCA256.OU=CA.O=DOC.C=GB<                         
  Subject's Name:                                            
       >CN=docec256.O=Doc.C=GB<                              
  Subject's AltNames:                                        
    IP: 127.0.0.1                                            
    Domain: localhost                                        
  Signing Algorithm: sha384ECDSA                             
  Key Usage: HANDSHAKE, DATAENCRYPT, DOCSIGN, KEYAGREE       
  Key Type: NIST ECC                                         
  Key Size: 256    
...                                         

It also gave me

Chain information:                                           
  Chain contains 1 certificate(s), chain is incomplete       

This message is because “A certificate chain is considered incomplete if RACF is unable to follow the chain back to a self-signed ‘root’ certificate”.

Which was true, RACF already had the CA in its database, and the CA certificate was not in the file.

When the file had already been imported I also got

Certificate 1:                                                     
Digital certificate information for CERTAUTH:
  Label: Linux-CARSA                                               

So I know it had already been imported into RACF.

I also got

Chain contains expired certificate(s)         

So I could tell I needed to get a newer certicate.

Add it to the RACF key store

There is no add-replace, so you have to delete it, then add it

RACDCERT DELETE - 
  (LABEL('DOCEC256')) ID(COLIN) 
RACDCERT ID(COLIN)    ADD('COLIN.DOCEC256.NEW.PEM') - 
  WITHLABEL('DOCEC256') 

SETROPTS RACLIST(DIGTNMAP, DIGTCRIT) REFRESH

The first time I ran this I got

RACDCERT DELETE   (LABEL('DOCEC256')) ID(COLIN)                                                           
IRRD107I No matching certificate was found for this user.                                                 
READY                                                                                                     
RACDCERT ID(COLIN)    ADD('COLIN.DOCEC256.NEW.PEM')   WITHLABEL('DOCEC256')                               
IRRD199I Certificate with label 'DOCEC256' is added for user COLIN.                                       
IRRD175I The new profile for DIGTCERT will not be in effect until a SETROPTS REFRESH has been issued.     

The second time I ran it I got

RACDCERT DELETE   (LABEL('DOCEC256')) ID(COLIN)                                                                   
IRRD176I RACLISTed profiles for DIGTCERT will not reflect the deletion(s) until a SETROPTS REFRESH is issued.     
READY                                                                                                             
RACDCERT ID(COLIN)    ADD('COLIN.DOCEC256.NEW.PEM')   WITHLABEL('DOCEC256')                                       
IRRD199I Certificate with label 'DOCEC256' is added for user COLIN.                                               
IRRD175I The new profile for DIGTCERT will not be in effect until a SETROPTS REFRESH has been issued.             

Refresh the RACLISTed data

If the classes are RACLISTed (cached in memory), you need

SETROPTS RACLIST(DIGTNMAP, DIGTCRIT) REFRESH

What happens if it is already in the key store under a different userid?

I tried adding it for a different userid and got

RACDCERT ID(ADCDA) ADD('COLIN.DOCEC256.NEW.PEM') WITHLABEL('DOCEC256')
IRRD109I The certificate cannot be added. Profile 0279.CN=SSCA256.OU=CA.O=DOC.C=GB is already defined.

Unfortunately it does not tell you the id it has already been defined for.

The only way I found of finding this information is

  • displaying all resources under class(DIGTCERT).
  • find the resource with the matching name.

For example

//COLRACF  JOB 1,MSGCLASS=H 
//S1  EXEC PGM=IKJEFT01,REGION=0M 
//SYSPRINT DD SYSOUT=* 
//SYSTSPRT DD SYSOUT=* 
//SYSTSIN DD * 
RLIST DIGTCERT  * 
/* 
// 

gave me output like

CLASS      NAME                                                  
-----      ----                                                  
DIGTCERT   0279.CN=SSCA256.OU=CA.O=DOC.C=GB                      
                                                                 
...                                                           
                                                                 
APPLICATION DATA                                                 
----------------                                                 
ADCDF                                                            

the current owner is ADCDF.

The serial number of the certificate is 0279, and the components are separated with periods ‘.’.

If the name has a blank in it you will get a value like

COLIN4Certification¢Authority.OU=TEST.O=COLIN

where the blank is replaced with the cent sign(¢).

Binary certificate, PKCS12, .P12

You should be able to upload the .p12 file to z/OS as a binary file and import it using the same JCL as above.

However in openssl V3 the packaging of the certificate has changed, and RACF does not yet support it.

The easiest way of getting a certificate into z/OS is to use the .pem file (grin)