On 2/12/26 3:43 PM, Zhuoying Cai wrote:
> DIAG 320 subcode 2 provides verification-certificates (VCs) that are in the
> certificate store. Only X509 certificates in DER format and SHA-256 hash
> type are recognized.
> 
> The subcode value is denoted by setting the second-left-most bit
> of an 8-byte field.
> 
> The Verification Certificate Block (VCB) contains the output data
> when the operation completes successfully. It includes a common
> header followed by zero or more Verification Certificate Entries (VCEs),
> depending on the VCB input length and the VC range (from the first VC
> index to the last VC index) in the certificate store.
> 
> Each VCE contains information about a certificate retrieved from
> the S390IPLCertificateStore, such as the certificate name, key type,
> key ID length, hash length, and the raw certificate data.
> The key ID and hash are extracted from the raw certificate by the crypto API.
> 
> Note: SHA2-256 VC hash type is required for retrieving the hash
> (fingerprint) of the certificate.
> 
> Signed-off-by: Zhuoying Cai <[email protected]>
> ---
>  docs/specs/s390x-secure-ipl.rst |  22 +++
>  hw/s390x/cert-store.h           |   3 +-
>  include/hw/s390x/ipl/diag320.h  |  50 +++++
>  target/s390x/diag.c             | 328 +++++++++++++++++++++++++++++++-
>  4 files changed, 400 insertions(+), 3 deletions(-)
> 
> diff --git a/docs/specs/s390x-secure-ipl.rst b/docs/specs/s390x-secure-ipl.rst
> index d3ece8a82d..22da589162 100644
> --- a/docs/specs/s390x-secure-ipl.rst
> +++ b/docs/specs/s390x-secure-ipl.rst
> @@ -38,3 +38,25 @@ Subcode 1 - query verification certificate storage 
> information
>      The output is returned in the verification-certificate-storage-size block
>      (VCSSB). A VCSSB length of 4 indicates that no certificates are available
>      in the CS.
> +
> +Subcode 2 - store verification certificates
> +    Provides VCs that are in the certificate store.
> +
> +    The output is provided in a VCB, which includes a common header followed 
> by
> +    zero or more verification-certificate entries (VCEs).
> +
> +    The instruction expects the cert store to
> +    maintain an origin of 1 for the index (i.e. a retrieval of the first
> +    certificate in the store should be denoted by setting first-VC to 1).
> +
> +    The first-VC index and last-VC index fields of VCB specify the range of 
> VCs
> +    to be stored by subcode 2. Stored count and remained count fields specify
> +    the number of VCs stored and could not be stored in the VCB due to
> +    insufficient storage specified in the VCB input length field.
> +
> +    Each VCE contains a header followed by information extracted from a
> +    certificate within the certificate store. The information includes:
> +    key-id, hash, and certificate data. This information is stored
> +    contiguously in a VCE (with zero-padding). Following the header, the
> +    key-id is immediately stored. The hash and certificate data follow and
> +    may be accessed via the respective offset fields stored in the VCE.

[...]

>  QEMU_BUILD_BUG_MSG(sizeof(VCStorageSizeBlock) != VCSSB_MIN_LEN,
>                     "size of VCStorageSizeBlock is wrong");
> +QEMU_BUILD_BUG_MSG(sizeof(VCBlock) != VCB_HEADER_LEN, "size of VCBlock is 
> wrong");
> +QEMU_BUILD_BUG_MSG(sizeof(VCEntry) != VCE_HEADER_LEN, "size of VCEntry is 
> wrong");
>  
>  void handle_diag_320(CPUS390XState *env, uint64_t r1, uint64_t r3, uintptr_t 
> ra)
>  {
> @@ -267,7 +585,8 @@ void handle_diag_320(CPUS390XState *env, uint64_t r1, 
> uint64_t r3, uintptr_t ra)
>           * for now.
>           */
>          uint32_t ism_word0 = cpu_to_be32(DIAG_320_ISM_QUERY_SUBCODES |
> -                                         DIAG_320_ISM_QUERY_VCSI);
> +                                         DIAG_320_ISM_QUERY_VCSI |
> +                                         DIAG_320_ISM_STORE_VC);
>  
>          if (s390_cpu_virt_mem_write(cpu, addr, r1, &ism_word0, 
> sizeof(ism_word0))) {
>              s390_cpu_virt_mem_handle_exc(cpu, ra);
> @@ -293,6 +612,13 @@ void handle_diag_320(CPUS390XState *env, uint64_t r1, 
> uint64_t r3, uintptr_t ra)
>          }
>          env->regs[r1 + 1] = rc;
>          break;

Subcode 2 should raise a specification exception if the address in
register r1 is not on a 4K‑byte boundary. I will handle this with the
appropriate changes in the next version.

> +    case DIAG_320_SUBC_STORE_VC:
> +        rc = handle_diag320_store_vc(cpu, addr, r1, ra, cs);
> +        if (rc == -1) {
> +            return;
> +        }
> +        env->regs[r1 + 1] = rc;
> +        break;
>      default:
>          env->regs[r1 + 1] = DIAG_320_RC_NOT_SUPPORTED;
>          break;


Reply via email to