# pvattest

Use `pvattest` to attest an IBM Secure Execution guest running on z16 and later.

With `pvattest` you can create attestation requests in a trusted environment and attest
an IBM Secure Execution for Linux guest to verify that a provider is running the correct image.
To achieve this, use the following commands:
  * `create` On a trusted system, creates an attestation request.
  * `perform` Performs an attestation measurement on the SE-guest to be attested. For this a
    attestation request is sent to the Ultravisor (UV) and the answer received. The `perform`
    command requires IBM z16 or later z/Architecture hardware.
  * `verify` On a trusted system, compares the answer from the Ultravisor to the
    expected answer. If they differ, the Secure Execution guest might be a different guest
    than expected, or not secure at all.

For meaningful results, run `create` and `verify` only in a trusted environment,
like your workstation or a previously attested IBM Secure Execution guest.
Otherwise, the attestation can be compromised.
For all certificates, revocation lists, and host-key documents, both the PEM and DER input
formats are supported. If you run this program on a non S390 System, 'perform' is not be available.

## Getting started

If all dependencies are met (see the s390-tools README) issue `make` in the source tree to build `pvattest`.

## Details
### create
`pvattest create` needs the host-key-document, a location to store the
attestation request protection key, and a location to store the request data.
Unless the `--no-verify` flag is set it additionally requires the IBM signing key
and the intermediate CA. The output contains the request in binary form which serves as input
to `pvattest perform`. Must be run in a trusted environment. Especially, do not create the request
on a system you want to attest. The attestation request protection key is valid for this request only,
must be kept until the verification is completed and must be destroyed afterwards
Keep the key secret.

### perform
`pvattest perform` needs a request in binary form generated by `pvattest create`and
a location to store the output. It will send the request to the device at `/dev/uv`
which passes the request to the Ultravisor.
Kernel will then send the request to the Ultravisor which will calculate the answer.
The Answer is then passed back to userspace and handled by `pvattest`
The output includes the original request and the answer from the Ultravisor.

### verify
`pvattest verify` needs the SE-guest header, the attestation request protection key,
and the attestation request and the response to the `pvattest perform` command from the Ultravisor.
It calculates the measurement in the trusted environment and compares it to the response from
the Ultravisor in the previous step.
The following return codes are possible:

0. successful verification: The calculated measurement matches the response from the Ultravisor

1. failed verification: The command ended with an error, for example, because of incorrect input or an invalid SE header

2. failed verification: The calculated measurement does not match the response from the Ultravisor

Run `pvattest verify` in a trusted environment. Especially, do not verify on the system you want to attest.

## Measurement
The measurement is a cryptographic measurement of the following block.
Only HMAC-SHA512 is supported.

| Start   | Size       | Content                                                       |
|---------|------------|---------------------------------------------------------------|
| 0x0     | 0x40       | Page List Digest (from SE header)                             |
| 0x40    | 0x40       | Address List Digest (from SE header)                          |
| 0x80    | 0x40       | Tweak List Digest (from SE header)                            |
| 0xc0    | 0x10       | SE Header Tag (from SE header)                                |
| 0xd0    | 0x10       | Configuration UID (generated by UV, included in the answer)   |
| 0xe0    | 0x02       | User Data Length (defined during measurement on the SE-guest) |
| 0xe2    | 0x02       | Zeros                                                         |
| 0xe4    | 0x04       | Additional Data Length (set by UV, included in the answer)    |
| 0xe8    | 0 - 0x100  | User Data (generated during measurement on the SE-guest)      |
| ...     | 0 or 0x10  | Optional Nonce (generated during request creation)            |
| ...     | 0 - 0x8000 | Additional Data (generated by UV, included in the answer)     |

### User Data
By default `pvattest` does not include any User Data, therefore the length is zero.
`User Data` is data generated by the SE guest and passed to UV during the measurement.
The `User Data` must be known to or be replicable by the verifier to verify the correctness of the User Data.
The addition of user data is currently an experimental setting.

### Additional Data
`Additional data` is data known to the Ultravisor. By default UV will not include any `Additional Data`.
Adding `Additional Data` is currently an experimental setting.

## Example

Create an attestation request in a trusted environment:

`pvattest create -k hkd.crt --arpk arp.key -o arcb.bin --cert IntermediateCA.crt --cert IbmSigningKey.crt`

Perform an attestation measurement on an IBM Secure Execution guest:

`pvattest perform --input arcb.bin --output measurement.bin`

Verify the response from the Ultravisor against the attestation request in a trusted environment:

`pvattest verify --input measurement.bin --arpk arp.key --hdr se_guest.hdr`
