Deploying a GREP11 server as a Confidential Computing Container Runtime instance with passthrough support

1. Prepare GREP11 server image

1.1 Download and Load the image.

Run the following command to load the grep11server image from the tar archive. If you don't have the tar archive, see Downloading Crypto Express Network API for Secure Execution Enclaves.

docker load -i grep11server-s390x_1.1.3.tar
 

The following snippet shows an example of the output:

Loaded image: sys-hpcs-team-grep11-docker-local.artifactory.swg-devops.com/grep11-c16:grep11server_s390x-1.1.3
 

1.2 Upload image to a Docker registry.

To build a Secure Execution VM, you must upload the grep11server image to a docker registry. The Docker registries that are supported are us.icr.io and https://index.docker.io/v1/.

For example:

API_KEY=<API-KEY>
docker login --username iamapikey -p $API_KEY us.icr.io
docker tag sys-hpcs-team-grep11-docker-local.artifactory.swg-devops.com/grep11-c16:grep11server_s390x-1.1.3 us.icr.io/crypto-appliance/grep11server:s390x-1.1.3
docker push us.icr.io/crypto-appliance/grep11server:s390x-1.1.3

USERNAME=<USERNAME>
PASSWORD=<PASSWORD>
docker login --username $USERNAME -p $PASSWORD docker.io
docker tag sys-hpcs-team-grep11-docker-local.artifactory.swg-devops.com/grep11-c16:grep11server_s390x-1.1.3 docker.io/hexiaohu/grep11server:s390x-1.1.3
docker push docker.io/hexiaohu/grep11server:s390x-1.1.3
 

Record the tag of the image that is required to construct docker-compose.yml or pod-compose.yml file for grep11server in Step 5.1.

2. Prepare configuration file for C16 client

You can configure the existing c16client.yaml file to deploy GREP11 server to use local passthrough CEX device or use Crypto Appliance API.

If the c16client.yaml file is not present, or when there is no server entry that is configured in this file, the C16 client uses local passthrough CEX device.

The following are the samples of c16client.yaml:

#trace, debug, info, warn, err, error, critical, off
loglevel: 'debug'
 
#trace, debug, info, warn, err, error, critical, off
loglevel: 'debug'
servers:
  - local: true
 

3. Assign Crypto domain to Secure Execution VM

To assign Crypto domains to secure execution VM, complete the following steps in KVM host:

  1. Run the lszcrypt -V command to get the Crypto domain details:

    lszcrypt -V
     

    Example:

    lszcrypt -V
    CARD.DOM TYPE  MODE        STATUS     REQUESTS  PENDING HWTYPE QDEPTH FUNCTIONS  DRIVER
    --------------------------------------------------------------------------------------------
    18       CEX8P EP11-Coproc online            0        0     14     08 -----XN-F- cex4card
    18.001c  CEX8P EP11-Coproc online            0        0     14     08 -----XN-F- cex4queue
    18.001d  CEX8P EP11-Coproc online            0        0     14     08 -----XN-F- cex4queue
    19       CEX8P EP11-Coproc online            0        0     14     08 -----XN-F- cex4card
    19.001c  CEX8P EP11-Coproc online            0        0     14     08 -----XN-F- cex4queue
    19.001d  CEX8P EP11-Coproc online            0        0     14     08 -----XN-F- cex4queue
     

    You can see the adapter ID and domain information. For example, in 18.001c , the adapter is 18 and the domain is 001c. The Crypto domain should match to the domain ("${HSM_DOMAIN}") in the grep11server.yaml file mentioned in Prepare configuration files for GREP11 server.

  2. Crypto domains control must be passed by a KVM host to guests. To do that:

    1. Load vfio_ap module to give control of Crypto domains to vfio_ap device driver:

      modprobe vfio_ap
       
    2. Free the domains from control of the zcrypt device driver. For more information, see Cryptographic adapter resources.

      echo 0x0 > /sys/bus/ap/apmask
       
      echo 0x0 > /sys/bus/ap/aqmask
       
  3. Create a mediated device:

    1. Run the uuidgen command to generate a 16-byte random value:

      uuid=$(uuidgen)
       
    2. Run the following command to create the device:

      echo ${uuid} > /sys/devices/vfio_ap/matrix/mdev_supported_types/vfio_ap-passthrough/create
       

    For more information, see Create a mediated device.

  4. Assign a Crypto adapter to the UUID that is generated in step 3.

    echo <adapter_id> > /sys/devices/vfio_ap/matrix/${uuid}/assign_adapter
     

    For Example:

    echo 0x18 > /sys/devices/vfio_ap/matrix/${uuid}/assign_adapter
     
  5. Assign a domain to the generated UUID:

    echo <domain_id> > /sys/devices/vfio_ap/matrix/${uuid}/assign_domain
     

    For Example:

    echo 0x001c > /sys/devices/vfio_ap/matrix/${uuid}/assign_domain
     
    Note: To assign multiple domains to a VSI, repeat steps 4 and 5 with different adapter and domain IDs to the same mediated device.
  6. Add the following data under the <devices> section (the section that includes UUID device) of the HPVS instance XML to ensure that the instance is assigned with one or more Crypto domains. For information about setting up an HPVS instance, see Setting up and configuring IBM Confidential Computing Container Runtime.

    <devices> 
      <hostdev mode='subsystem'  type='mdev' managed='no' model='vfio-ap'>
            <source>
                <address uuid='<uuid>'/> 
            </source>
        </hostdev>
    </devices>  
    </domain>
     

4. Prepare configuration files for GREP11 server

Prepare and collect the following certificates. For more information, see Creating OpenSSL certificates for GREP11 Servers.

Filename Description
grep11server.yaml GREP11 server configuration file
grep11-ca.pem GREP11 server CA certificates(used as CA root on GREP11 server side in mTLS connection)
grep11-server.key GREP11 server private key(used as server key on GREP11 server side in mTLS connection)
grep11-server.pem GREP11 server certificates(used as server certificate on GREP11 server side in mTLS connection)

Sample of grep11server.yaml:

#
# Copyright IBM Corp. All Rights Reserved.
#
# SPDX-License-Identifier: Apache-2.0
#
logging:
  # Package log levels
  # Levels: info, warning, debug, error, fatal, trace, and panic
  levels:
    # example below
    # entry: debug
###################################
## GRPC SERVICES TALKING TO GREP11 server ##
ep11crypto:
  enabled: true
  connection:
    address: 0.0.0.0
    port: 9876
    # Secure connection TLS options
    tls:
      enabled: true
      # certfile, keyfile and cacert refer to the pem files that holds the certs
      certfile: /cfg/grep11-server.pem
      keyfile: /cfg/grep11-server.key
      mutual: true
      cacert: /cfg/grep11-ca.pem
      # same as above, but instead of filename, contents of PEM can be in an environment
      # variable (i.e. to avoid mounting files into Docker container)
      cacertbytes:
      certfilebytes:
      keyfilebytes:
    # Server TCP/IP connection monitoring
    # serverKeepaliveTime is the duration in seconds after which if the server
    # does not see any activity from the client it pings the client to see
    # if it is alive
    # serverKeepaliveTimeout is the duration the server waits for a response
    # from the client after sending a ping before closing the connection
    keepalive:
      serverKeepaliveTime: 30
      serverKeepaliveTimeout: 5
  # card.domain tuple and domain are hex numbers
  # i.e. "01.00a9" corresponds to 169th domain on first card.
  domain: "${HSM_DOMAIN}"
 
Note: HSM_DOMAIN must match with what is specified in crypto-pt subsection of contract for local passthrough support. Only one domain is supported.

5. Deploy GREP11 server

You can deploy GREP11 server either on a local s390x environment or as a Confidential Computing Container Runtime instance.

5.1 Deploy GREP11 on a local s390x environment

5.1.1 Prepare file

Prepare docker-compose.yml to boot up the GREP11 server container.

Note: Change the image tag to grep11server image

Sample of docker-compose.yml:

services:
  ep11server:
    user: "0"
    image: ${GREP11SERVER_IMAGE_TAG}
    privileged: true
    ports:
      - 9876:9876
    volumes:
      - ./c16client.yaml:/etc/c16/c16client.yaml
      - ./grep11server.yaml:/etc/ep11server/ep11server.yaml
      - ./grep11-ca.pem:/cfg/grep11-ca.pem
      - ./grep11-server.pem:/cfg/grep11-server.pem
      - ./grep11-server.key:/cfg/grep11-server.key
 

GREP11SERVER_IMAGE_TAG is the grep11server image tag; for example: "us.icr.io/crypto-appliance/grep11server:s390x-1.1.3@sha256:54334c919a93c45f70d0252d8518d24b64255a88a073b35239f95d056d444ab8"

Note: c16client.yaml can be empty. However, if debug trace is needed, c16client.yaml is required and the trace level should be set as "debug".

5.1.2 Deploy container locally

Run the following command to deploy the grep11server container on a local s390x server.

docker-compose up
 

5.2 Deploy GREP11 server as Confidential Computing Container Runtime instance.

Complete the following steps to deploy the GREP11 server as an HPCR instance:

5.2.1 Prepare compose file

You can either go with Docker or Podman method to prepare archive for grep11server container.

5.2.1.2 Podman:

For single or multiple containers, you can use the play subsection. In the play subsection, you can define the workload via Pod descriptors. Each pod can contain one or more container definitions. Descriptors can be provided as shown in the following example:

apiVersion: v1
kind: Pod
metadata:
  name: grep11server
spec:
  securityContext:
    privileged: true
  containers:
  - name: grep11server
    image: us.icr.io/crypto-appliance-test/sys-hpcs-team-grep11-docker-local.artifactory.swg-devops.com/grep11-c16:grep11server_s390x-1.0.0@sha256:7a6e20bd9c7aa5bc155212247859fcd5ee01d0005d123561e68fec3fa4452abe
    volumeMounts:
    - name: c16-client
      mountPath: /etc/c16/c16client.yaml
    - name: grep11-config
      mountPath: /etc/ep11server/ep11server.yaml
    - name: grep11-ca
      mountPath: /cfg/grep11-ca.pem
    - name: grep11-server-pem
      mountPath: /cfg/grep11-server.pem
    - name: grep11-server-key
      mountPath: /cfg/grep11-server.key
    securityContext:
      privileged: true
    ports:
    - containerPort: 9876
      hostPort: 9876
  volumes:
  - name: c16-client
    hostPath:
      path: ./c16client.yaml
      type: FileOrCreate
  - name: grep11-config
    hostPath:
      path: ./grep11server.yaml
      type: FileOrCreate
  - name: grep11-ca
    hostPath:
      path: ./grep11-ca.pem
      type: FileOrCreate
  - name: grep11-server-pem
    hostPath:
      path: ./grep11-server.pem
      type: FileOrCreate
  - name: grep11-server-key
    hostPath:
      path: ./grep11-server.key
      type: FileOrCreate
  restartPolicy: Always
 

5.2.2 Create archive

Run the following command to generate the Base64 value of compose.tgz:

tar -czvf compose.tgz docker-compose.yml c16client.yaml grep11server.yaml grep11-ca.pem grep11-server.key grep11-server.pem
base64 -i compose.tgz | tr -d '\n' > compose.b64
 
Note: Here, c16client.yaml is an optional file.

5.2.3 Prepare contract

You can skip this step if contract is already prepared as in Preparation of Crypto Passthrough contract.

5.2.3.1 The env section

Prepare the env.yaml contract file including crypto-pt, host-attestaion, logging, and volumes subsections.

Example:

type: env
logging:
  syslog:
    hostname: ${RSYSLOG_SERVER_IP}
    port: 6514
    server: "${RSYSLOG_SERVER_ROOT_CA}"
    cert: "${RSYSLOG_CLIENT_CA}"
    key: "${RSYSLOG_CLIENT_KEY}"
volumes:
  test0:
    seed: stsolutiontest
crypto-pt:
  lock: true
  index-1:
    type: secret
    domain-id: "18.001c"
    secret: aokwkosss
    mkvp: 0x6e80520d911c4ac425b28523a707a68dc55d77658d83e29d4e2ed45000000000
  index-2:
    type: pvsecret
    domain-id: "19.001c"
    pvsecret: 5JRm94TmlCSWI
    pvsecret-crt: <pvsecret-verify-crt>
    mkvp: 0xc3c459b6dd08b91d18e1fca4544692f45de3c414dce11da74773459e00000000
host-attestation:
  HKD-3931-*******:
    description: London_MZR1
    host-key-doc: <A Host Key Document encoded in base64>
  HKD-3931-*******:
    description: London_MZR2
    host-key-doc: <A Host Key Document encoded in base64>
 

For information about creating secret, see Crypto passthrough contract preparation.

Note: The other parts of the env subsection like Logging and volumes are not explained here. See Logging section and Volumes section to include them as part of the contract. A typical unencrypted contract to create grep11server is Crypto unencrypted contract

5.2.3.2 The workload section

Update the auths section to indicate the logon method of the Docker registry in which the grep11server image is located. Using us.icr.io as an example:

type: workload
auths:
  us.icr.io:
    password: ${API_KEY}
    username: iamapikey
play:
  archive: ${PLAY_VALUE}
volumes:
  testvolume:
    mount: "/mnt/data"
    seed: "workload_seed"
    filesystem: "ext4"
  env:
    key: "value"
 

The following are the parameters:

  • API_KEY: It is the Docker registry access token.
  • PLAY_VALUE: It is the Base64 encoding of the file compose.tgz. This is the value that is created as part of Create grep11 archive

For more information, see the workload section.

5.2.3.3 Generate encrypted contract

  1. Get the worklaod.yaml file from workload section.
  2. Get the env.yaml file from env section.
WORKLOAD="$(pwd)/workload.yaml"
CONTRACT_KEY=${CONTRACT_KEY}
PASSWORD="$(openssl rand 32 | base64 -w0)"
ENCRYPTED_PASSWORD="$(echo -n "$PASSWORD" | base64 -d | openssl rsautl -encrypt -inkey $CONTRACT_KEY -certin | base64 -w0 )"
ENCRYPTED_WORKLOAD="$(echo -n "$PASSWORD" | base64 -d | openssl enc -aes-256-cbc -pbkdf2 -pass stdin -in "$WORKLOAD" | base64 -w0)"
echo "workload: \"hyper-protect-basic.${ENCRYPTED_PASSWORD}.${ENCRYPTED_WORKLOAD}\"" > contract_encrypt.txt
ENV="$(pwd)/env.yaml"
CONTRACT_KEY=${CONTRACT_KEY}
PASSWORD="$(openssl rand 32 | base64 -w0)"
ENCRYPTED_PASSWORD="$(echo -n "$PASSWORD" | base64 -d | openssl rsautl -encrypt -inkey $CONTRACT_KEY  -certin | base64 -w0)"
ENCRYPTED_ENV="$(echo -n "$PASSWORD" | base64 -d | openssl enc -aes-256-cbc -pbkdf2 -pass stdin -in "$ENV" | base64 -w0)"
echo "env: \"hyper-protect-basic.${ENCRYPTED_PASSWORD}.${ENCRYPTED_ENV}\"" >> contract_encrypt.txt
 
Note: CONTRACT_KEY is the file path of the encryption certificate.

5.2.5 Verify GREP11 server deployment

You can use the nmap tool to verify the on-prem or on Cloud deployment by checking the port status of the GREP11 server. If the port status is Open, the grep11server runs normally.

For example:

nmap -A -T4 -p 9876 <SE_VM_IP>
For example:
    nmap -A -T4 -p 9876 169.48.158.229
    nmap -A -T4 -p 9876 150.238.54.207
$ nmap -A -T4 -p 9876 169.48.158.229
Starting Nmap 7.92 ( https://nmap.org ) at 2022-08-06 08:44 CST
Nmap scan report for 169.48.158.229
Host is up (0.19s latency).
PORT     STATE SERVICE VERSION
9876/tcp open  ssl/sd?
| ssl-cert: Subject: commonName=169.48.158.229/organizationName=IBM/stateOrProvinceName=California/countryName=US
| Subject Alternative Name: DNS:127.0.0.1:9876, DNS:localhost:9876, DNS:9.47.152.236:9876, DNS:9.47.152.179:9876, DNS:150.238.54.207:9876, DNS:169.48.158.229:9876, IP Address:127.0.0.1, IP Address:169.48.158.229, IP Address:9.47.152.236, IP Address:9.47.152.179, IP Address:150.238.54.207
| Not valid before: 2022-08-04T01:11:10
|_Not valid after:  2024-08-03T01:11:10
Service detection performed. Report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 44.30 seconds
 

5.2.6 View logs

You can view logs that are collected on any configured logging server.

6. Configure GREP11 client with enabled mTLS authentication

If you want to access Cloud HSM on IBM Cloud Confidential Computing Container Runtime remotely to perform cryptographic operations, you need to generate a GREP11 API request in your on-prem environment to enable mutual TLS authentication for GREP11 API instead of IBM Cloud IAM authentication.

Prepare the following mutual TLS client certificates for connection with GREP11 server:

Filename Description
grep11-ca.pem GREP11 server CA certificates (Used as CA root on GREP11 server side in mTLS connection.)
grep11-client.key GREP11 client private key
grep11-client.pem GREP11 client public certificate

Add the following snippet into your code:

cert, _ := tls.LoadX509KeyPair("grep11-client.pem ", "grep11-client.key")
var callOpts = []grpc.DialOption{
  grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{Certificates: []tls.Certificate{cert}}))
}
 

Now, you can perform cryptographic operations by remotely accessing the functions with the Enterprise PKCS #11 (EP11) over gRPC API calls. For more information, see Cryptographic operations: GREP11 API.