Re: [PATCH v16 09/33] s390x/diag: Implement DIAG 320 subcode 2

2026-07-15 Thread Collin Walling


Reviewed-by: Collin Walling 

-- 
Regards,
  Collin



[PATCH v16 09/33] s390x/diag: Implement DIAG 320 subcode 2

2026-07-07 Thread Zhuoying Cai
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 
Reviewed-by: Eric Farman 
Reviewed-by: Jared Rossi 
---
 docs/specs/s390x-secure-ipl.rst |  24 +++
 include/hw/s390x/ipl/diag320.h  |  38 
 target/s390x/diag.c | 316 +++-
 3 files changed, 377 insertions(+), 1 deletion(-)

diff --git a/docs/specs/s390x-secure-ipl.rst b/docs/specs/s390x-secure-ipl.rst
index 201cc74c7c..99052041c1 100644
--- a/docs/specs/s390x-secure-ipl.rst
+++ b/docs/specs/s390x-secure-ipl.rst
@@ -42,3 +42,27 @@ 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 and last-VC fields of the VCB specify the index range of
+VCs to be stored in the VCB. Certs are stored sequentially, starting
+with first-VC index. As each cert is stored, a "stored count" is
+incremented. If there is not enough space to store all certs requested
+by the index range, a "remaining count" will be recorded and no more
+certificates will be stored.
+
+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.
diff --git a/include/hw/s390x/ipl/diag320.h b/include/hw/s390x/ipl/diag320.h
index d37d8eaa86..7fda2d44fd 100644
--- a/include/hw/s390x/ipl/diag320.h
+++ b/include/hw/s390x/ipl/diag320.h
@@ -12,19 +12,45 @@
 
 #define DIAG_320_SUBC_QUERY_ISM 0
 #define DIAG_320_SUBC_QUERY_VCSI1
+#define DIAG_320_SUBC_STORE_VC  2
 
 #define DIAG_320_RC_OK  0x0001
 #define DIAG_320_RC_NOT_SUPPORTED   0x0102
 #define DIAG_320_RC_INVAL_VCSSB_LEN 0x0202
+#define DIAG_320_RC_INVAL_VCB_LEN   0x0204
+#define DIAG_320_RC_BAD_RANGE   0x0302
 
 #define DIAG_320_ISM_QUERY_SUBCODES 0x8000
 #define DIAG_320_ISM_QUERY_VCSI 0x4000
+#define DIAG_320_ISM_STORE_VC   0x2000
 
 #define VCSSB_NO_VC 4
 #define VCSSB_LEN_VALID   128
 
 #define CERT_NAME_MAX_LEN  64
 
+/*
+ * If the VCE flags indicate an invalid certificate,
+ * the VCE length is set to 72, containing only the
+ * first five fields of VCEntry.
+ */
+#define VCE_INVALID_LEN 72
+
+#define DIAG_320_VCE_FLAGS_VALID0x80
+
+typedef enum Diag320VceKeyType {
+DIAG_320_VCE_KEYTYPE_SELF_DESCRIBING = 0,
+DIAG_320_VCE_KEYTYPE_ECDSA_P521 = 1,
+} Diag320VceKeyType;
+
+typedef enum Diag320VceFormat {
+DIAG_320_VCE_FORMAT_X509_DER = 1,
+} Diag320VceFormat;
+
+typedef enum Diag320VceHashType {
+DIAG_320_VCE_HASHTYPE_SHA2_256 = 1,
+} Diag320VceHashType;
+
 struct VCStorageSizeBlock {
 uint32_t length;
 uint8_t reserved0[3];
@@ -60,6 +86,12 @@ struct VCEntryHeader {
 };
 typedef struct VCEntryHeader VCEntryHeader;
 
+struct VCEntry {
+VCEntryHeader vce_hdr;
+uint8_t cert_buf[];
+};
+typedef struct VCEntry VCEntry;
+
 struct VCBlockHeader {
 uint32_t in_len;
 uint32_t reserved0;
@@ -74,4 +106,10 @@ struct VCBlockHeader {
 };
 typedef struct VCBlockHeader VCBlockHeader;
 
+struct VCBlock {
+VCBlockHeader vcb_hdr;
+uint8_t vce_buf[];
+};
+typedef struct VCBlock VCBlock;
+
 #endif
diff --git a/target/s390x/diag.c b/target/s390x/diag.c
index 6eff77fc5b..5221bb1956 1