When using MQ AMS to encrypt MQ messages, it has been very frustrating to get messages like
CSQ0217E %MQPA CSQ0COPN Failed to process object ‘recipient public key certificate in recipient keyring’
and not know what the problem is. (Especially when the cause is recipient public key certificate is not in recipient keyring.
System SSL which provides all of the encryption has a trace capability. You enable it when you start AMS, so you have the overhead in normal operation.
It sometimes writes data to a file in Unix, other times you need to start GKSRVR and collect the CTRACE.
With AMS the trace data is written to a file in Unix. Use the unix gsktrace command to format it.
gsktrace gskssl.16777257.trc > gsk
Configuring the trace
In the AMS JCL procedure //ENVARS DD DSN=….,DISP=SHR
I have
#######################################################################
#
# GSKIT Trace
#
# If you are having problems with certificates and missing entries in
# key stores you can enable GSKIT trace to help diagnose the problems.
#
# To enable/disable GSKIT trace, un-comment and update the following
# environment variables as required.
#
# GSK_TRACE_FILE - Specifies the name of the trace file in Unix
# System Services (USS). Insert the correct user
# name and ensure you set the correct permissions
# on the directories and files to allow the
# user ID in use by IBM MQ for z/OS Advanced
# Message Security to write the resulting trace
# file. The current process identifier is included
# as part of the trace file name when the name
# contains a percent sign (%). The gsktrace command
# can be entered in USS to format the trace:
#
# e.g. gsktrace gskssl.84017302.tr
#
# GSK_TRACE - Specifies a bit mask that enables System SSL trace
# options to trace gsk_* calls. All trace options are
# enabled if the bit mask is 0xff and all trace
# options are disabled if the bit mask is 0x00.
GSK_TRACE_FILE=/tmp/gskssl.%.trc
#SK_TRACE=0xff everything including payloads
GSK_TRACE=0x0f just control stuff
If you specify GSK_TRACE=0xff you get a lot of data – including all the application data ( message content + any headers etc).
I found GSK_TRACE=0x0f provides what I need.
A first look at the data
There is data like
08/06/2026-07:00:49 Thd-0 ENTRY gsk_open_keyring(): ---> Keyring 'STCMQ/drq.ams.keyring'
08/06/2026-07:00:49 Thd-0 ENTRY crypto_generate_random_bytes(): ---> Length 20
08/06/2026-07:00:49 Thd-0 EXIT crypto_generate_random_bytes(): <--- Exit status 0x00000000 (0)
08/06/2026-07:00:49 Thd-0 INFO gsk_open_keyring(): Record 'AMS' is the default key
08/06/2026-07:00:49 Thd-0 INFO gsk_open_keyring(): Identifier 1 assigned to 'AMS'
08/06/2026-07:00:49 Thd-0 ENTRY gsk_decode_certificate(): --->
08/06/2026-07:00:49 Thd-0 EXIT gsk_decode_certificate(): <--- Exit status 0x00000000 (0)
08/06/2026-07:00:49 Thd-0 INFO gsk_open_keyring(): Identifier 2 assigned to 'NEW-CA'
08/06/2026-07:00:49 Thd-0 ENTRY gsk_decode_certificate(): --->
08/06/2026-07:00:49 Thd-0 EXIT gsk_decode_certificate(): <--- Exit status 0x00000000 (0)
08/06/2026-07:00:49 Thd-0 INFO gsk_open_keyring(): Identifier 3 assigned to 'DOCZOSCA'
08/06/2026-07:00:49 Thd-0 ENTRY gsk_decode_certificate(): --->
08/06/2026-07:00:49 Thd-0 EXIT gsk_decode_certificate(): <--- Exit status 0x00000000 (0)
08/06/2026-07:00:49 Thd-0 INFO gsk_open_keyring(): Identifier 4 assigned to 'AMS2'
08/06/2026-07:00:49 Thd-0 ENTRY gsk_decode_certificate(): --->
08/06/2026-07:00:49 Thd-0 EXIT gsk_decode_certificate(): <--- Exit status 0x00000000 (0)
08/06/2026-07:00:49 Thd-0 ENTRY gsk_decode_certificate_extension(): ---> Decoding
08/06/2026-07:00:49 Thd-0 EXIT gsk_decode_certificate_extension(): <--- Exit status
08/06/2026-07:00:49 Thd-0 ENTRY gsk_decode_certificate_extension(): ---> Decoding
08/06/2026-07:00:49 Thd-0 EXIT gsk_decode_certificate_extension(): <--- Exit status
08/06/2026-07:00:49 Thd-0 INFO gsk_build_issuer_chains(): Record 'NEW-CA' is issuer for ...
08/06/2026-07:00:49 Thd-0 INFO gsk_build_issuer_chains(): Record 'NEW-CA' is self-signed
08/06/2026-07:00:49 Thd-0 INFO gsk_build_issuer_chains(): Record 'DOCZOSCA' is self-signed
08/06/2026-07:00:49 Thd-0 ENTRY gsk_decode_certificate_extension(): ---> Decoding ...
08/06/2026-07:00:49 Thd-0 EXIT gsk_decode_certificate_extension(): <--- Exit status ...
08/06/2026-07:00:49 Thd-0 INFO gsk_build_issuer_chains(): No issuer found for record 'AMS2'
08/06/2026-07:00:49 Thd-0 EXIT gsk_open_keyring(): <--- Exit status 0x00000000 (0) Handle...
- I ignore the date
- I use the time to match the records to when the problem occurred. It is HH:MM:SS granularity
- Thd-0, Thd-15. Work runs on AMS tasks. A task can run work for any userid. I’ve often found one thread does the processing for the putters and the getters. You have to guess when one piece of work ends, and the next starts.
- ENTRY/EXIT/INFO this is the entry, exit, or just some information about the function
- gsk_open_keyring() is the function. This is described in Cryptographic Services System Secure Sockets Layer Programming (SC14-7495-60) which I think is only available in PDF format.
The trace shows records between
- ENTRY gsk_open_keyring(): —> Keyring ‘STCMQ/drq.ams.keyring’
- EXIT gsk_open_keyring(): <— Exit status 0x00000000
Showing the function gsk_open_keyring(): worked successfully.
It shows the elements on the keyring
INFO gsk_open_keyring(): Record 'AMS' is the default key
INFO gsk_open_keyring(): Identifier 1 assigned to 'AMS'
INFO gsk_open_keyring(): Identifier 2 assigned to 'NEW-CA'
INFO gsk_open_keyring(): Identifier 3 assigned to 'DOCZOSCA'
INFO gsk_open_keyring(): Identifier 4 assigned to 'AMS2'
How do you find the problem?
You might have the time of day when the problem occurred. The trace is only HH:MM:SS, so there may be a lot of records.
I use ISPF edit.
- X ALL
- Find ‘Exit status’ all
- exclude ‘Exit status 0x00000000’ all
This shows just the Exit status which are non zero. This should localise the problem.
Periodically it uses a new file – so check you are using the latest file.
Some records showing a problem
ENTRY gsk_validate_certificate(): ---> Data source count=1
ENTRY gsk_validate_certificate_mode(): ---> Data source count=1,...
ENTRY cms_validate_certificate_mode_int(): ---> Data source count=1,...
INFO cms_validate_certificate_mode_int(): validate root=566,...
ENTRY gsk_name_to_dn(): --->
EXIT gsk_name_to_dn(): <--- Exit status 0x00000000 (0) DN: CN=START1,O=AMS,C=TEST
INFO cms_validate_certificate_mode_int(): Validating CN=START1,O=AMS,C=TEST
INFO cms_validate_certificate_mode_int(): No Signature Algorithm List Provided
ENTRY gsk_decode_certificate_extension(): ---> Decoding certificate extension type 2
EXIT gsk_decode_certificate_extension(): <--- Exit status 0x00000000 (0)
INFO get_issuer_certificate(): Using AuthorityKeyIdentifier to locate issuer
ENTRY gsk_name_to_dn(): --->
EXIT gsk_name_to_dn(): <--- Exit status 0x00000000 (0) DN: CN=NEW-CA2,OU=TEST,O=COLIN
INFO get_issuer_certificate(): Using issuer CN=NEW-CA2,OU=TEST,O=COLIN
ENTRY gsk_get_record_by_subject_mode(): ---> Handle 275787C0
EXIT gsk_get_record_by_subject_mode(): <--- Exit status 0x0335300e (53817358)
ERROR validate_certificate(): Unable to get issuer certificate: Error 0x03353024
ERROR validate_certificate_mode(): Unable to validate certificate: Error 0x03353024
This shows data is being processed from the message.
- ENTRY gsk_name_to_dn(): —> shows data was passed in to routine to convert from the transmission (internal) format DN to a readable name
- EXIT gsk_name_to_dn(): <— Exit status 0x00000000 (0) DN: CN=START1,O=AMS,C=TEST The output name is CN=START1,O=AMS,C=TEST
- INFO get_issuer_certificate(): get the issuer name from the certificate
- EXIT gsk_name_to_dn(): <— Exit status 0x00000000 (0) DN: CN=NEW-CA2,OU=TEST,O=COLIN this is the decoded issuer name
- INFO get_issuer_certificate(): Using issuer CN=NEW-CA2,OU=TEST,O=COLIN look for the certificate with this DN in the keyring
- EXIT gsk_get_record_by_subject_mode(): <— Exit status 0x0335300e It could not find the record in the keyring with the given subject DN.
- Looking in the documentation gives 0335300E : Record not found.