Generating ICSF keys using Diffie-Hellman

The Diffie-Hellman technique allows you to create keys on two system securely, with no need to share a common key. Each system needs a private/public key pair, and the public keys are available on all systems. There are many steps but it is relatively painless.

Scenario

Two systems A and B. We want to have a data set encryption key on system A copied to system B and to create an exporter key on A, and a matching importer key on B.

The steps are

  • generate private/public pairs on each system
  • use these to generate the symmetric keys.

Generate a private/public key pair on each system, and send the public key to the other system.

On System A

Use the ISPF ICSF panels

  • Options 5;6;6 Generate PKA keys, import or export public keys via certificate
    • Enter PKDS record’s label: SYSTEMA
    • Select Generate a new RSA or EC key pair record
    • Select EC NIST Curve, P521.
    • This should display PKDS Key Request Successful. Press enter to return.
    • Select Export the PKDS record’s public key to a certificate data set
    • Specify a data set name ‘COLIN.SYSTEMA’
    • Specify the common name SYSTEMA
    • Press enter
    • This should give you PKDS Public Key Export Successful
  • Send the data set ‘COLIN.SYSTEMA’ to the remote system.

On System B

  • Follow the instructions above to generate PKA keys.
    • Label Name SYSTEMB, and use export data set name COLIN.SYSTEMB, etc. Check it has worked.
    • Next, select Create a PKDS public key record from an input certificate
    • Enter the name of the data set you copied across containing the public key for SYSTEMA
    • Press enter. It should import the key
    • F3 to return to the ICSF PDKS keys page.
    • Select option 1, and press enter. Use the line command K to display the contents of the certificates. You should have the private key with sections “PRIVATE PUBLIC”, and the public key should have section “PUBLIC”
  • Send the data set ‘COLIN.SYSTEMB’ to the first system.

On System A

  • Read in the data set
  • Options 5;6;6 Generate PKA keys, import or export public keys via certificate
  • Enter PKDS record label SYSTEMB
  • Select Create a PKDS public key record from an input certificate
  • Enter the name of the data set COLIN.SYSTEMB.
  • When this has worked, display the contents of the PKDS as described above.

You now have a private/public key on each system, and each system has a copy of the other’s public key.

Generate a symmetric key on each system

Now you have the private/public key on each system, and the public key of the other system, you can create a key.

ICSF does not provide a function for this. See Generate a secure shared key on multiple systems using Diffie-Hellman in Github.

  • On SYSTEMA you need the name of the private/public pair SYSTEMA, and the name of the public certificate SYSTEMB.
  • You need a phrase which provides a seed to the encryption. This does not need to be kept confidential, but you may still wish to protect it.

Generate a CIPHER for data set encryption

//RUN      EXEC PGM=GENDH,REGION=0M,PARMDD=MYPARMS 
//MYPARMS DD *
-ptype INTERNAL,AES,CIPHER,XPRTCPAC,ANY-MODE
-key AESDHDSCIPHER
-private AAA
-public BBB
-replace Y
-party cOlinSeed
-debug 0
/*
//STEPLIB DD DISP=SHR,DSN=COLIN.LOAD
//SYSPRINT DD SYSOUT=*,DCB=(LRECL=200)
//CEEDUMP DD SYSOUT=*,DCB=(LRECL=200)
//SYSOUT DD SYSOUT=*
//SYSERR DD SYSOUT=*

On the other system change AAA and BBB, and run the JCL.

Create an exporter key on SYSTEMA

//RUN      EXEC PGM=GENDH,REGION=0M,PARMDD=MYPARMS 
//MYPARMS DD *
-ptype INTERNAL,AES,EXPORTER
-key AESDHKEK
-private AAA
-public BBB
-replace Y
-party cOlinSeed2
-debug 0
/*
//STEPLIB DD DISP=SHR,DSN=COLIN.LOAD
//SYSPRINT DD SYSOUT=*,DCB=(LRECL=200)
//CEEDUMP DD SYSOUT=*,DCB=(LRECL=200)
//SYSOUT DD SYSOUT=*
//SYSERR DD SYSOUT=*

Create a matching importer key on SYSTEMB

//RUN      EXEC PGM=GENDH,REGION=0M,PARMDD=MYPARMS 
//MYPARMS DD *
-ptype INTERNAL,AES,IMPORTER
-key AESDHKEK
-private BBB
-public AAA
-replace Y
-party cOlinSeed2
-debug 0
/*
//STEPLIB DD DISP=SHR,DSN=COLIN.LOAD
//SYSPRINT DD SYSOUT=*,DCB=(LRECL=200)
//CEEDUMP DD SYSOUT=*,DCB=(LRECL=200)
//SYSOUT DD SYSOUT=*
//SYSERR DD SYSOUT=*

You can now use exporter key AESDHKEK on system A, and importer KEK AESDHKEK on system B.

Idiot’s guide to TCPIP connectivity

I had a working TCPIP network, and made a few “improvements”. Unfortunately these improvements sometimes stopped the connectivity between systems, and I had a frustrating time understanding the problems and fixing them. The idiot in the blog post is me, for next time when I need to connect boxes together.

In concept TCPIP connectivity is simple – it is, but there are some subtle, non obvious things you need to be aware of.

As I was writing this post I found I did not know really how IPV4 worked, because it used “the wrong” IP address but still worked.

I found many ways of failing to connect to TCPIP, and some complex ways of getting it to work – I just wanted a simple way of being able to ping z/OS from my laptop. It is complicated by some definitions need to be done in order, and doing things in a different order sometimes worked, sometimes did not.

Basic TCPIP concepts that every one should know

  • The term socket is used by applications to communicate with TCP/IP, not where you connect a network/phone cable.
  • Think of a connection between two boxes. I have a yellow Ethernet cable between them. There are several terms for the where the cable is plugged in. A common term is the interface.
  • IP addresses
    • Each end of the connection has one or more IP addresses.  I think of it as having plastic labels tied to the end of the cable.
    • IPV6 addresses beginning with fe… and ff… are used by (internal use) advanced technology and can be ignored. You can use them, but the addresses may change every time the connection is started, which makes it hard to automate using them.
    • The system may generate some IPV6 addresses, but you can define your own. The system generated an address like 2a00:9999:8888:7777:894e:9876:781:32f1. Sometimes parts of these (the right hand part) are randomised (to make it harder for people to observer traffic patterns and so hack your system).
    • I use addresses like 2001:db8::f which are shorter to type.
    • On z/OS an IPV4 interface can have only one IP address. An IPV6 interface can have multiple addresses see ADDADDR. On z/OS an interface can be IPV4 or IPV6 but not both.
    • On Linux, an interface can have multiple IPV4, and multiple IPV6 addresses (but only the first IPV4 may be visible to applications)
    • For IPV6, TCP/IP can generate its own IPV6 addresses for internal processing, such as routing.
  • To get data from this machine to that machine over the yellow Ethernet cable, you have a route definition like “for this range of remote addresses use the yellow Ethernet cable, which has the address xxxx at the far end.
  • If you use TCP/IP to send a request, you usually want a response to come back. As well as defining a route to get to the remote end, you need a route defined to get from the remote machine back to the local machine. A ping request can fail because
    • The local end does not have a valid route to the remote end. The packet could be sent to the wrong place(down the wrong cable), or just discarded.
    • An intermediate box does not have a route to the remote end.
    • The remote end receives the request but does not have a route definition to send the response back to the requester.
    • An intermediate box does not have a route to the local end.
    • A firewall says no.
    • You can use the traceroute command to find the path taken to the remote end. This will tell you the path it took to get there. It does not tell you the route back. For this you need to issue the traceroute command on the remote end, and perhaps on intermediate boxes.
  • You define a route from this box using the yellow cable with label xxxx on it. The remote end of the cable has IP address….
  • You need at least two route statements
    • to get the data from the local system to the remote system,
    • the remote system needs a route statement to get to the local system.
  • You can find these address using
    • the Linux command ip -6 addr or ip -4 addr for TCP IPV6 and IPV4 respectively.
    • the z/OS command TSO NETSTAT HOME
  • Subnet: an IP V6 address has 32 hex digits. These are broken up into groups of 16 eg 2001:0DB8… This can be written as 2001:db8… The subnet specified which bits are significant when routing packets to the router. With z/OS usually the top 64 bits are used. This is written as …./64.
  • An address 2001:db8:9::1/64 is in a different subnet to address 2001:db8:8::1/64.
  • Address 2001:db8:8:1::2/64 is in the same subnet as 2001:db8:8:1::3 because only the top 64 bits count towards the subnet (2001:db8:8:1).
  • A gateway is a network point that acts as an entrance to another network. On the Internet, a node or stopping point can be either a gateway node or a host (end-point) node. Both the computers of Internet users and the computers that serve pages to users are host nodes. A gateway can have one protocol in, and output the data in a different protocol. For example I have broadband coming to my house. The gateway router converts this to TCP/IP, and converts it to wireless.

Things that you may not know

  • My end of a connection has two IP addresses defined. If I ping a remote site it uses the first IP address in its list, the remote site sees a packet of data from the first IP address in the list. You may have configured a route at the remote system to get back to your local system, but if you define your local addresses in a different order, a different IP address will be sent – and the remote end may not have a route for it.
  • If the interface at the next machine has two IP addresses 10.1.0.3 and 7.168.1.2 , I have to use the first IP address in the list defining a route sudo ip -4 route add 7.168.1.74 via 10.1.0.3 dev enp0s31f6. If I delete the first address, then I need to use the 7.168.1.2

Python could not read a data set I sent from z/OS USS.

I created a file in Unix System Services, and FTPed it down to my Linux box. I could edit it, and process it with no problems, until I came to read in the file using Python.

Python gave me

File “<frozen codecs>”, line 322, in decode
UnicodeDecodeError: ‘utf-8’ codec can’t decode byte 0xb8 in position 3996: invalid start byte

The Linux command file pagentn.txt gave me

pagentn.txt: ISO-8859 text

whereas other files had ASCII text.

I changed my Python program to have

with open(“/home/colinpaice/python/pagentn.txt”,encoding=”ISO-8859-1″) as file:

and it worked!

I browsed the web, and found a Python way of finding the code page of a file

import chardet    
rawdata = open(infile, 'rb').read()
result = chardet.detect(rawdata)
charenc = result['encoding']

it returned a dict with

result {‘encoding’: ‘ISO-8859-1’, ‘confidence’: 0.73, ‘language’: ”}

Why does it take an application using TCPIP, so long to start?

I had problems with a couple of applications taking over 30 seconds to start. For example FTP and the RMF DDS Server.


I found this was cause by my TCPIP resolver was misconfigured. An application can ask DNS for the IP address(10.1.1.2) or the string address (BBC.CO.UK) from the TCPIP Resolver function. On my system this was configured in ADCD.Z31A.TCPPARMS(GBLTDATA) as

LOOKUP DNS LOCAL

This says, go to the network, and ask the DNS server “out there” for information. If this request times out, use the local information. On my system the path to the DNS server was not configured, so it waited, and eventually timed out.

When I changed the LOOKUP definition to

LOOKUP LOCAL

it came up with no delays.

Debugging the “you do not have access to something, but I’m not telling you what” problem

The problem, I had a message

SSL Handshake Failed, ICSF error. Review ‘RACF CSFSERV Resource Requirements’ of the z/OS documentation.
Reason: The webservers userid does not have access to CSFSERV resource classes required for SSL.

But it does not tell me what it does not have access to.

When an application tries to access a resource, and the userid is not authorised to that resource, RACF can produce an error message, which tells you the resource name.

If the application asks “does this application have access to this resource”, then RACF produces no error message, and it is up to the application to provide a sensible and useful message.

Collecting a RACF trace

You can use a command

#SET TRACE(CLASS(CSFSERV),RACROUTE(ALL))

to turn on the trace for that class. You can also use USERID(…) and jobname(…) to further restrict what is traced.

The output goes to GTF.

s gtf,gtf
01 AHL125A  RESPECIFY TRACE OPTIONS OR REPLY U 
 1,trace=usrp                                                                                 
IEE600I REPLY TO 01 IS;TRACE=USRP                                                              
    09.53.19 STC00315  TRACE=USRP                                                                                     
02 AHL101A  SPECIFY TRACE EVENT KEYWORDS --USR=                                                
  - 09.53.27           r 2,usr=(F44),end                                                                              
    09.53.27 STC00315  IEE600I REPLY TO 02 IS;USR=(F44),END                                                           
    09.53.27 STC00315  USR=(F44),END                                                                                  
    09.53.27 STC00315  AHL103I  TRACE OPTIONS SELECTED --USR=(F44)                                                    
  | 09.53.27 STC00315 *03 AHL125A  RESPECIFY TRACE OPTIONS OR REPLY U                                                 
00- 09.53.30           r 3,u                                                                                          
    09.53.30 STC00315  IEE600I REPLY TO 03 IS;U                                                                       
    09.53.30 STC00315  U                                                                                              

Run your work.

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

if you do not get “THE FOLLOWING TRACE DATASETS CONTAIN TRACE DATA…” it means you did not collect any data.

Use IPCS to look at it

  • =0 and specify the trace data set name
  • if you change scope to both it will remember the data for next time
  • =6 to get you to IPCS Subcommand Entry panel
  • if this is the first time you have used this instance of the data set, you should issue the dropd command to get IPCS to forget about previous usage
  • gtf usr(all) This displays the data
  • You can process this
    • type M and press PF8 to get to the bottom of the data
    • report view will display the data in ISPF edit (view mode)
    • You can now issue commands like
    • x all
    • f code all and look for non zero return codes.
    • del all x
    • sort 30 50 to display all return codes in numerical order. You need to look at the top and the bottom.
    • make a note of the return code ( copy the line to your clipboard)
    • quit
    • report view
    • find return code

To get rid of some of the forest of unhelpful data

  • x all
  • find ‘ ‘ 1 20 all
  • find ‘+’ 1 2 all
  • delete all nx

#SET TRACE(NOCLASS,RACROUTE(ALL))

Upgrade to Ubuntu 24.04 – whoops I’ve lost my network connections

I used remote access to upgrade my Ubuntu server. After the upgrade I could not connect over Ethernet. ( I could not access over Wi-Fi, but that was a different problem).

If I pinged from either end, it did not connect.

On my server, the network server for the network connection wired, did not have a MAC address specified. I used the pull down and selected it. I do not know if this is relevant.

My laptop had address 10.1.0.2, and the server had address 10.10.0.3.

On the server the command

ip addr

gave

2: eno1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 ...
inet 10.1.0.3/24 brd 10.1.0.255 scope global noprefixroute eno1

I used the command

sudo ip route add 10.1.0.2 dev eno1

to define the route, and connectivity was temporarily restored. I could ping from either machine.

Digging deeper

The command

grep -i warn /var/log/syslog

gave

NetworkManager[1457]: <warn>  [...] keyfile: load: "/etc/NetworkManager/system-connections/eno1": failed to load connection: File permissions (100604) are insecure

ls -ltr /etc/NetworkManager/system-connections/eno1

gave

-rw----r-- 1 root root 376 Oct 21 2022 /etc/NetworkManager/system-connections/eno1

Where file permission xxx604 is -rw—-r–, which allows “other” to read the file

The command

sudo chmod o-r /etc/NetworkManager/system-connections/*

removes the “other” read permission.The next reboot gave me connectivity back.

Lessons learned

After doing an upgraded, (or perhaps once a week) display the syslog for warn and error and resolve any problems.

Ubuntu 24.04 upgrade. tp-link wifi did not work

I upgraded from 22.04 to 24.04 and my plug-in Wi-Fi tp-link device did not work.

What device do I have ?

The command

lsusb

gave me

Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 001 Device 002: ID 17ef:4515 Lenovo Lenovo Portable HDD
Bus 001 Device 003: ID 2357:0109 TP-Link TL-WN823N v2/v3 [Realtek RTL8192EU]

but the command

sudo lshw -c network

did not show me any wireless definitions.

Fixing the problem

I followed the instructions in https://github.com/Mange/rtl8192eu-linux-driver.

The files you need may already be on your machine for earlier versions of Ubuntu, you may not need to download anything.

Because my server had no Wi-Fi connection, I used git to download the latest code to my laptop onto a USB device, and then used the USB device on the server machine. You may not need to do this.

I used the instructions to

  • sudo dkms uninstall rtl8192eu/1.0 to uninstall the driver and
  • sudo dkms remove rtl8192eu/1.0 –all to delete the drive
  • reboot
  • then followed the instructions.

Without the uninstall and remove the install did not activate the drivers.

Migrating from Ubuntu 22.04 to 24.04

Overall this was pretty painless, but did have a few problems on the way.

Could not contact web sites

I used the Software Updater application to upgrade to 24.04. This could not get to some sites. This is because some git hub keys had expired. (EXPKEYSIG 23F3D4EA75716059) See here for the solution.

  • Copy the long command to the clip board and execute it.
  • I do not think I needed to reinstall gh. ( I cannot test this because my migration was a success)

Disk space

The install complained that I did not have enough free space on /.

I removed various products: thunderbirds, libreoffice, gcc (theses get re-installed as part of the upgrade). I emptied the rubbish bin.

I removed some of the snaps.

The command snap list –all lists all of the currently installed snaps. The output is like

Name            Version       Rev Tracking      Publisher   Notes
gnome-3-38-2004 0+git.efb213a 143 latest/stable canonical** -
gnome-3-38-2004 0+git.6f39565 140 latest/stable canonical** disabled
...

My snap is configured to keep two revisions around.

I deleted the older versions

snap remove “gnome-3-38-2004″ –revision=”140”

I did not want to delete all versions, in case my upgrade to 24.04 failed, and I stayed on 22.04 for a while longer.

The upgrade took several hours,and seemed to work.

Rebooted into command line

After it had finished installing, I rebooted, and it booted into a command line – not the full screen mode.

I had been caught like this before, and used the command

sudo apt install –resinstall ubuntu-desktop

to reinstall gnome.

The next boot worked.

What’s different?

gedit

gedit is not installed by default. You can use apt to install it. The replacements is gnome-text-editor. I created an alias in ~/.bashrc

alias gte='gnome-text-editor'

so I can type gte…. to open a file.

parcellite did not work

I used this as my clip board manager. I started it, but it did nothing. A little while later it did work.

I installed copyq which provides more capability than parcellite.

I used settings -> Keyboard -> Keyboard Shortcuts > Custom shortcuts to create a short cut to copyq menu.

I used dash -> show apps -> startup applications to add copyq.

Touchpad speed

I still needed to use

echo 250 |sudo tee /sys/devices/platform/i8042/serio1/serio2/sensitivity

to make my touchpad sensitive to movement. You can also tweak/sys/devices/platform/i8042/serio1/serio2/speed.

I also found the command xset m 4/1 0 but I haven’t played with it

Why has it gone dark?

I use my laptop with a dual monitor, and the laptop was very dark (to the point of being almost unreadable). After a bit of faffing around the laptop brightness controls worked, and the screen came back to normal.

I also found

cat /sys/class/backlight/intel_backlight/brightness
cat /sys/class/backlight/intel_backlight/max_brightness

which gave me brightness 1365 and max_brightness 1515.

You can change the brightness using

echo 1000| sudo tee /sys/class/backlight/intel_backlight/brightness

This may be due to auto-dimming. Settings -> Power -> Power savings dim screen.

Lenovo server problems

When I ran sudo apt update, I got messages like

W: Skipping acquisition of configured file ‘sutton.simon/dep11/icons-64×64@2.tar’, as repository ‘http://lenovo.archive.canonical.com noble InRelease’ doesn’t have the component ‘sutton.simon’ (component misspelt in sources.list?)

I issued commands

  • sudo mv /etc/apt/sources.list.d/oem-sutton.simon-banning-meta.sources ~/sources.list.d.oem-sutton.simon-banning-meta.sources
  • sudo mv /etc/apt/sources.list.d/oem-sutton.simon-banning-meta.list.distUpgrade ~/sources.list.d.oem-sutton.simon-banning-meta.list.distUpgrade

and it seems to have cured the problem.

One minute mvs: data set file system (/dsfs) on z/OS

There is a good overview of dsfs here.

My understanding of how dsfs works is that you can access z/OS datasets, members and spool, through a Unix file system interface, and so use commands like “ls”. When you read a member, it is read into the dsfs file system, and the Unix commands work on this data. When you write to the Unix file, it is written to the dsfs file system, and when the file is closed, the data is written to the dataset.

Some information is cached in the dsfs file system, and some definitions, such as DCB information on a per userid basis is also stored.

DSFS is defined to OMVS as a Physical File System. Part of the definition of the PFS is the started task name. When the PFS is defined to OMVS, it starts the DSFS started task.

To stop it, you issue a command to OMVS to stop the PFS.

Permissions

The dsfs started task has threads which do work. When you issue a request, one of the threads becomes your userid and accesses the data sets, so there is no change to the standard RACF data set protection.

User defaults

You can define defaults for when data sets are created. These are user dependant. To issue these for another user, you have to become a super user to become that id, and then issue the dfsadm command.

Changing configuration

You can change the configuration file and restart DSFS (which will be disruptive).

You can make changes to the active system (which are not saved) using the omvs command

Diagnosis

Messages are produced, and are documented in the M&C manual. if you get a reason code, you can use bpxmtext code to display the meaning of the code.

Creating data sets and members from /dsfs

You can configure defaults when using dsfs to create data sets and members. For example

Creating a PDS(E)

cd /dsfs/txt/colin
dsadm createparm -path . -pdsmodel "dsntype(library) dsorg(po) lrecl(133) recfm(vb)
blksize(0)"

For path /dsfs/txt/colin (-path .) it creates a model for pds (-pdsmodel) with the parameters dsntype…blksize(0)

Note:blksize(0) says “pick the best block size”

You can display this using

dsadm fileinfo   -path /dsfs/txt/colin  

and get

path: /dsfs/txt/colin                                                                                
fid 49,1 anode 1285,4548
length 16384 format BLOCKED
1K blocks 16 dir tree status VALID
PDS model anode 31,60 PS model anode 0,0
object type DIR object linkcount 181
object genvalue 0x00000000 dir version 1
dir name count 431 data set name type HLQ DIR
recfm na lrecl na
data mode TEXT data set status RETRIEVED
data set name COLIN
ENQ held NO
direct blocks 0x00001BAF 0x00001BB0 0xFFFFFFFF 0xFFFFFFFF
0xFFFFFFFF 0xFFFFFFFF 0xFFFFFFFF 0xFFFFFFFF
indirect blocks 0xFFFFFFFF 0xFFFFFFFF 0xFFFFFFFF
mtime Sep 9 10:09:55 2024 atime Sep 9 10:09:55 2024
ctime Sep 9 10:09:55 2024 create date Sep 9 2024
not encrypted not compressed
PDS model dsntype(library) dsorg(po) lrecl(133) recfm(vb) blksize(0)
PS model na
vnode,vntok 0x00000050,,0x072003C0 0x0099A7F0,,0x00000000
opens oi=0 rd=0 wr=0
file segments na file unscheduled na
meta buffers 0 dirty meta buffers 2

Creating a sequential file

dsadm createparm -path /dsfs/txt/colin -psmodel "dsorg(ps) lrecl(80) recfm(fb) blksize(3200)"

The command

dsadm fileinfo   -path /dsfs/txt/colin 

now gives

PS model               dsorg(ps) lrecl(80) recfm(fb) blksize(3200)    

The command

echo "hi" > /dsfs/txt/colin/seq2          

creates a data set COLIN.SEQ2 with characteristics

Record format . . . : FB
Record length . . . : 80
Block size . . . . : 3200

If you specify blksize(0) the system applies a default. In my case Block size . . . . : 27920, which makes good usage of the disk space.

Different data set types

There are three data set types

  • bin – binary for example load modules
  • rec – records
  • txt – text files, with a new line character “at the end of the line”

You can define the data set characteristics for each of these.