This is part of some work I did to configure AT-TLS for a JES2 TCPIP node to another system.
I didn’t have a remote system to connect to, but I had a Python TLS server which the NJE node could connect to (and then end), which demonstrated the TLS connection.
The JES2 definition
The address of the remote end, running the Python TLS server was 10.1.0.2.
$ADDSOCKET(LAPTOP),IPADDR=10.1.0.2,LINE=3,NETSRV=1,NODE=50,PORT=2175,SECURE=NO
Starting the NJE node
$SN,SOCKET=LAPTOP
The AT-TLS definitions
This definition acts as a client to a remote server, so AT-TLS needs to be configured as a AT-TLS client.
TTLSRule CPJES2OUT
{
RemoteAddr 10.1.0.2
RemotePortRange 2175
Direction Output
TTLSGroupAction
{
TTLSEnabled On
}
TTLSEnvironmentAction
{
HandshakeRole Client
TTLSEnvironmentAdvancedParms
{
# clientAuthType needs to be required or Passthru
ClientAuthType PassThru
TLSv1 Off
TLSv1.1 Off
TLSv1.2 On
# TLSv1.3 On
}
TTLSKeyringParms AZFKeyringParms
{
Keyring start1/TN3270
}
TTLSConnectionAction
{
TTLSCipherParmsRef AZFCipherParms
TTLSConnectionAdvancedParms
{
# ServerCertificateLabel is for a server connection
# ServerCertificateLabel RSA2048
CertificateLabel RSA2048
# ApplicationControlled OFF
}
}
}
AZFCipherParms
I put common definitions into their own section, for example
TTLSCipherParms AZFCipherParms
{
V3CipherSuites TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256
V3CipherSuites TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384
V3CipherSuites TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
V3CipherSuites TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384
V3CipherSuites TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
V3CipherSuites TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
V3CipherSuites TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
V3CipherSuites TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
# TLSv1.3
V3CipherSuites TLS_CHACHA20_POLY1305_SHA256
}
Using TLSv1.3
You need TTLSEnvironmentAdvancedParms to contain
TTLSEnvironmentAdvancedParms
{
TLSv1.1 Off
TLSv1.2 On
TLSv1.3 On
}
and at least one TLSV1.3 cipher spec.
TTLSCipherParms AZFCipherParms
{
# TLSv1.2
V3CipherSuites TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256
V3CipherSuites TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384
V3CipherSuites TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
V3CipherSuites TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384
V3CipherSuites TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
V3CipherSuites TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
V3CipherSuites TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
# TLSv1.3
V3CipherSuites TLS_CHACHA20_POLY1305_SHA256
# TLSv1.2
V3CipherSuites4Char TLS_CHACHA20_POLY1305_SHA256
V3CipherSuites4Char TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384
V3CipherSuites4Char TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256
V3CipherSuites4Char TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 C02
}
such as TLS_CHACHA20_POLY1305_SHA256
See Cipher suite definitions and search for 1301 (TLS_AES_128_GCM_SHA256) ,1302 (TLS_AES_256_GCM_SHA384) ,1303(TLS_CHACHA20_POLY1305_SHA256).
There is a column called TLSv1.3 (but it is hard to find). There are two tables, you need to use the second table to find what version of TLS the cipher specs provide.
Python server
The code below acted as a remote TLS server for the handshake.
import socket
import ssl
import struct
import pprint
HOST= ''
PORT = 2175
cafile="/home/colinpaice/ssl/ssl2/jun24/docca256.pem"
certfile="/home/colinpaice/ssl/ssl2/jun24/docec521june.pem"
keyfile="/home/colinpaice/ssl/ssl2/jun24/docec521june.key.pem"
certpassword = None
context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
context.minimum_version = ssl.TLSVersion.TLSv1_2
context.maximum_version = ssl.TLSVersion.TLSv1_3
context.load_cert_chain(certfile, keyfile)
context.load_verify_locations(cafile=cafile)
context.verify_mode = ssl. CERT_REQUIRED
getciphers = context.get_ciphers()
#for gc in getciphers:
# print("get cipher",gc)
with socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0) as sock:
sock.bind((HOST, PORT))
sock.listen(1)
with context.wrap_socket(sock, server_side=True) as ssock:
conn, addr = ssock.accept()
cert = conn.getpeercert()
pprint.pprint(cert)
v = conn.version()
print("version",v)
c = conn.cipher()
print("ciphers",c)
sock.close
When this ran, and the z/OS NJE node connected to it ($SN,SOCKET=LAPTOP), the output was
{'issuer': ((('organizationName', 'COLIN'),),
(('organizationalUnitName', 'CA'),),
(('commonName', 'DocZosCA'),)),
'notAfter': 'Jun 17 23:59:59 2025 GMT',
'notBefore': 'Jun 17 00:00:00 2024 GMT',
'serialNumber': '07',
'subject': ((('organizationName', 'RSA2048'),),
(('organizationalUnitName', 'SSS'),),
(('commonName', '10.1.1.2'),)),
'subjectAltName': (('IP Address', '10.1.1.2'),),
'version': 3}
version TLSv1.3
ciphers ('TLS_CHACHA20_POLY1305_SHA256', 'TLSv1.3', 256)
Showing the certificate, the level of TLS and the cipher spec used.
The messages on the z/OS console were
$SN,SOCKET=LAPTOP
$HASP000 OK
IAZ0543I NETSRV1 TCP/IP connection with IP Addr: 10.1.0.2 Port: 2175
Initiated
IAZ0543I NETSRV1 TCP/IP connection with IP Addr: 10.1.0.2 Port: 2175
Successful
IAZ0543I NETSRV1 TCP/IP connection with IP Addr: ::ffff:10.1.0.2 Port:
2175 ended due to TCP/IP error, rc: 1121